```
-The `useRef` Hook returns an object with a single property called `current`. Initially, `myRef.current` will be `null`. When React creates a DOM node for this `
`, React will put a reference to this node into `myRef.current`. You can then access this DOM node from your [event handlers](/learn/responding-to-events) and use the built-in [browser APIs](https://developer.mozilla.org/docs/Web/API/Element) defined on it.
+`useRef` Hook 返回一个对象,该对象有一个名为 `current` 的属性。最初,`myRef.current` 是 `null`。当 React 为这个 `
` 创建一个 DOM 节点时,React 会把对该节点的引用放入 `myRef.current`。然后,你可以从 [事件处理器](/learn/responding-to-events) 访问此 DOM 节点,并使用在其上定义的内置[浏览器 API](https://developer.mozilla.org/docs/Web/API/Element)。
```js
-// You can use any browser APIs, for example:
+// 你可以使用任意浏览器 API,例如:
myRef.current.scrollIntoView();
```
-### Example: Focusing a text input {/*example-focusing-a-text-input*/}
+### 示例: 使文本输入框获得焦点 {/*example-focusing-a-text-input*/}
-In this example, clicking the button will focus the input:
+在本例中,单击按钮将使输入框获得焦点:
@@ -64,7 +66,7 @@ export default function Form() {
<>
- Focus the input
+ 聚焦输入框
>
);
@@ -73,18 +75,18 @@ export default function Form() {
-To implement this:
+要实现这一点:
-1. Declare `inputRef` with the `useRef` Hook.
-2. Pass it as `
`. This tells React to **put this `
`'s DOM node into `inputRef.current`.**
-3. In the `handleClick` function, read the input DOM node from `inputRef.current` and call [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on it with `inputRef.current.focus()`.
-4. Pass the `handleClick` event handler to `
` with `onClick`.
+1. 使用 `useRef` Hook 声明 `inputRef`。
+2. 像 ` ` 这样传递它。这告诉 React **将这个 ` ` 的 DOM 节点放入 `inputRef.current`。**
+3. 在 `handleClick` 函数中,从 `inputRef.current` 读取 input DOM 节点并使用 `inputRef.current.focus()` 调用它的 [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)。
+4. 用 `onClick` 将 `handleClick` 事件处理器传递给 ``。
-While DOM manipulation is the most common use case for refs, the `useRef` Hook can be used for storing other things outside React, like timer IDs. Similarly to state, refs remain between renders. Refs are like state variables that don't trigger re-renders when you set them. For an introduction to refs, see [Referencing Values with Refs.](/learn/referencing-values-with-refs)
+虽然 DOM 操作是 ref 最常见的用例,但 `useRef` Hook 可用于存储 React 之外的其他内容,例如计时器 ID 。与 state 类似,ref 能在渲染之间保留。你甚至可以将 ref 视为设置它们时不会触发重新渲染的 state 变量!你可以在[使用 Ref 引用值](/learn/referencing-values-with-refs)中了解有关 ref 的更多信息。
-### Example: Scrolling to an element {/*example-scrolling-to-an-element*/}
+### 示例: 滚动至一个元素 {/*example-scrolling-to-an-element*/}
-You can have more than a single ref in a component. In this example, there is a carousel of three images. Each button centers an image by calling the browser [`scrollIntoView()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) method the corresponding DOM node:
+一个组件中可以有多个 ref。在这个例子中,有一个由三张图片和三个按钮组成的轮播,点击按钮会调用浏览器的 [`scrollIntoView()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView) 方法,在相应的 DOM 节点上将它们居中显示在视口中:
@@ -193,27 +195,27 @@ li {
-#### How to manage a list of refs using a ref callback {/*how-to-manage-a-list-of-refs-using-a-ref-callback*/}
+#### 如何使用 ref 回调管理 ref 列表 {/*how-to-manage-a-list-of-refs-using-a-ref-callback*/}
-In the above examples, there is a predefined number of refs. However, sometimes you might need a ref to each item in the list, and you don't know how many you will have. Something like this **wouldn't work**:
+在上面的例子中,ref 的数量是预先确定的。但有时候,你可能需要为列表中的每一项都绑定 ref ,而你又不知道会有多少项。像下面这样做**是行不通的**:
```js
{items.map((item) => {
- // Doesn't work!
+ // 行不通!
const ref = useRef(null);
return ;
})}
```
-This is because **Hooks must only be called at the top-level of your component.** You can't call `useRef` in a loop, in a condition, or inside a `map()` call.
+这是因为 **Hook 只能在组件的顶层被调用。**不能在循环语句、条件语句或 `map()` 函数中调用 `useRef` 。
-One possible way around this is to get a single ref to their parent element, and then use DOM manipulation methods like [`querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) to "find" the individual child nodes from it. However, this is brittle and can break if your DOM structure changes.
+一种可能的解决方案是用一个 ref 引用其父元素,然后用 DOM 操作方法如 [`querySelectorAll`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/querySelectorAll) 来寻找它的子节点。然而,这种方法很脆弱,如果 DOM 结构发生变化,可能会失效或报错。
-Another solution is to **pass a function to the `ref` attribute.** This is called a [`ref` callback.](/reference/react-dom/components/common#ref-callback) React will call your ref callback with the DOM node when it's time to set the ref, and with `null` when it's time to clear it. This lets you maintain your own array or a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), and access any ref by its index or some kind of ID.
+另一种解决方案是**将函数传递给 `ref` 属性**。这称为 [`ref` 回调。](/reference/react-dom/components/common#ref-callback) 当需要设置 ref 时,React 将传入 DOM 节点来调用你的 ref 回调,并在需要清除它时传入 `null` 。这使你可以维护自己的数组或 [Map](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map),并通过其索引或某种类型的 ID 访问任何 ref。
-This example shows how you can use this approach to scroll to an arbitrary node in a long list:
+此示例展示了如何使用此方法滚动到长列表中的任意节点:
@@ -235,7 +237,7 @@ export default function CatFriends() {
function getMap() {
if (!itemsRef.current) {
- // Initialize the Map on first usage.
+ // 首次运行时初始化 Map。
itemsRef.current = new Map();
}
return itemsRef.current;
@@ -318,7 +320,7 @@ li {
-In this example, `itemsRef` doesn't hold a single DOM node. Instead, it holds a [Map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map) from item ID to a DOM node. ([Refs can hold any values!](/learn/referencing-values-with-refs)) The [`ref` callback](/reference/react-dom/components/common#ref-callback) on every list item takes care to update the Map:
+在这个例子中,`itemsRef` 保存的不是单个 DOM 节点,而是保存了包含列表项 ID 和 DOM 节点的 [Map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)。([Ref 可以保存任何值!](/learn/referencing-values-with-refs)) 每个列表项上的 [`ref` 回调](/reference/react-dom/components/common#ref-callback)负责更新 Map:
```js
{
const map = getMap();
if (node) {
- // Add to the Map
+ // 添加到 Map
map.set(cat.id, node);
} else {
- // Remove from the Map
+ // 从 Map 删除
map.delete(cat.id);
}
}}
>
```
-This lets you read individual DOM nodes from the Map later.
+这使你可以之后从 Map 读取单个 DOM 节点。
-## Accessing another component's DOM nodes {/*accessing-another-components-dom-nodes*/}
+## 访问另一个组件的 DOM 节点 {/*accessing-another-components-dom-nodes*/}
-When you put a ref on a built-in component that outputs a browser element like ` `, React will set that ref's `current` property to the corresponding DOM node (such as the actual ` ` in the browser).
+当你将 ref 放在像 ` ` 这样输出浏览器元素的内置组件上时,React 会将该 ref 的 `current` 属性设置为相应的 DOM 节点(例如浏览器中实际的 ` ` )。
-However, if you try to put a ref on **your own** component, like ` `, by default you will get `null`. Here is an example demonstrating it. Notice how clicking the button **does not** focus the input:
+但是,如果你尝试将 ref 放在 **你自己的** 组件上,例如 ` `,默认情况下你会得到 `null`。这个示例演示了这种情况。请注意单击按钮 **并不会** 聚焦输入框:
@@ -366,7 +368,7 @@ export default function MyForm() {
<>
- Focus the input
+ 聚焦输入框
>
);
@@ -375,7 +377,7 @@ export default function MyForm() {
-To help you notice the issue, React also prints an error to the console:
+为了帮助您注意到这个问题,React 还会向控制台打印一条错误消息:
@@ -383,9 +385,9 @@ Warning: Function components cannot be given refs. Attempts to access this ref w
-This happens because by default React does not let a component access the DOM nodes of other components. Not even for its own children! This is intentional. Refs are an escape hatch that should be used sparingly. Manually manipulating _another_ component's DOM nodes makes your code even more fragile.
+发生这种情况是因为默认情况下,React 不允许组件访问其他组件的 DOM 节点。甚至自己的子组件也不行!这是故意的。Refs 是一个应急方案,应该谨慎使用。手动操作 _另一个_ 组件的 DOM 节点会使你的代码更加脆弱。
-Instead, components that _want_ to expose their DOM nodes have to **opt in** to that behavior. A component can specify that it "forwards" its ref to one of its children. Here's how `MyInput` can use the `forwardRef` API:
+相反,_想要_ 暴露其 DOM 节点的组件必须**选择**该行为。一个组件可以指定将它的 ref “转发”给一个子组件。下面是 `MyInput` 如何使用 `forwardRef` API:
```js
const MyInput = forwardRef((props, ref) => {
@@ -393,13 +395,13 @@ const MyInput = forwardRef((props, ref) => {
});
```
-This is how it works:
+它是这样工作的:
-1. ` ` tells React to put the corresponding DOM node into `inputRef.current`. However, it's up to the `MyInput` component to opt into that--by default, it doesn't.
-2. The `MyInput` component is declared using `forwardRef`. **This opts it into receiving the `inputRef` from above as the second `ref` argument** which is declared after `props`.
-3. `MyInput` itself passes the `ref` it received to the ` ` inside of it.
+1. ` ` 告诉 React 将对应的 DOM 节点放入 `inputRef.current` 中。但是,这取决于 `MyInput` 组件是否允许这种行为, 默认情况下是不允许的。
+2. `MyInput` 组件是使用 `forwardRef` 声明的。 **这让从上面接收的 `inputRef` 作为第二个参数 `ref` 传入组件**,第一个参数是 `props` 。
+3. `MyInput` 组件将自己接收到的 `ref` 传递给它内部的 ` `。
-Now clicking the button to focus the input works:
+现在,单击按钮聚焦输入框起作用了:
@@ -421,7 +423,7 @@ export default function Form() {
<>
- Focus the input
+ 聚焦输入框
>
);
@@ -430,13 +432,13 @@ export default function Form() {
-In design systems, it is a common pattern for low-level components like buttons, inputs, and so on, to forward their refs to their DOM nodes. On the other hand, high-level components like forms, lists, or page sections usually won't expose their DOM nodes to avoid accidental dependencies on the DOM structure.
+在设计系统中,将低级组件(如按钮、输入框等)的 ref 转发到它们的 DOM 节点是一种常见模式。另一方面,像表单、列表或页面段落这样的高级组件通常不会暴露它们的 DOM 节点,以避免对 DOM 结构的意外依赖。
-#### Exposing a subset of the API with an imperative handle {/*exposing-a-subset-of-the-api-with-an-imperative-handle*/}
+#### 使用命令句柄暴露一部分 API {/*exposing-a-subset-of-the-api-with-an-imperative-handle*/}
-In the above example, `MyInput` exposes the original DOM input element. This lets the parent component call `focus()` on it. However, this also lets the parent component do something else--for example, change its CSS styles. In uncommon cases, you may want to restrict the exposed functionality. You can do that with `useImperativeHandle`:
+在上面的例子中,`MyInput` 暴露了原始的 DOM 元素 input。这让父组件可以对其调用`focus()`。然而,这也让父组件能够做其他事情 —— 例如,改变其 CSS 样式。在一些不常见的情况下,你可能希望限制暴露的功能。你可以用 `useImperativeHandle` 做到这一点:
@@ -450,7 +452,7 @@ import {
const MyInput = forwardRef((props, ref) => {
const realInputRef = useRef(null);
useImperativeHandle(ref, () => ({
- // Only expose focus and nothing else
+ // 只暴露 focus,没有别的
focus() {
realInputRef.current.focus();
},
@@ -469,7 +471,7 @@ export default function Form() {
<>
- Focus the input
+ 聚焦输入框
>
);
@@ -478,28 +480,28 @@ export default function Form() {
-Here, `realInputRef` inside `MyInput` holds the actual input DOM node. However, `useImperativeHandle` instructs React to provide your own special object as the value of a ref to the parent component. So `inputRef.current` inside the `Form` component will only have the `focus` method. In this case, the ref "handle" is not the DOM node, but the custom object you create inside `useImperativeHandle` call.
+这里,`MyInput` 中的 `realInputRef` 保存了实际的 input DOM 节点。 但是,`useImperativeHandle` 指示 React 将你自己指定的对象作为父组件的 ref 值。 所以 `Form` 组件内的 `inputRef.current` 将只有 `focus` 方法。在这种情况下,ref “句柄”不是 DOM 节点,而是你在 `useImperativeHandle` 调用中创建的自定义对象。
-## When React attaches the refs {/*when-react-attaches-the-refs*/}
+## React 何时添加 refs {/*when-react-attaches-the-refs*/}
-In React, every update is split in [two phases](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom):
+在 React 中,每次更新都分为 [两个阶段](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom):
-* During **render,** React calls your components to figure out what should be on the screen.
-* During **commit,** React applies changes to the DOM.
+* 在 **渲染** 阶段, React 调用你的组件来确定屏幕上应该显示什么。
+* 在 **提交** 阶段, React 把变更应用于 DOM。
-In general, you [don't want](/learn/referencing-values-with-refs#best-practices-for-refs) to access refs during rendering. That goes for refs holding DOM nodes as well. During the first render, the DOM nodes have not yet been created, so `ref.current` will be `null`. And during the rendering of updates, the DOM nodes haven't been updated yet. So it's too early to read them.
+通常,你 [不希望](/learn/referencing-values-with-refs#best-practices-for-refs) 在渲染期间访问 refs。这也适用于保存 DOM 节点的 refs。在第一次渲染期间,DOM 节点尚未创建,因此 `ref.current` 将为 `null`。在渲染更新的过程中,DOM 节点还没有更新。所以读取它们还为时过早。
-React sets `ref.current` during the commit. Before updating the DOM, React sets the affected `ref.current` values to `null`. After updating the DOM, React immediately sets them to the corresponding DOM nodes.
+React 在提交阶段设置 `ref.current`。在更新 DOM 之前,React 将受影响的 `ref.current` 值设置为 `null`。更新 DOM 后,React 立即将它们设置到相应的 DOM 节点。
-**Usually, you will access refs from event handlers.** If you want to do something with a ref, but there is no particular event to do it in, you might need an Effect. We will discuss effects on the next pages.
+**通常,你将从事件处理器访问 refs。** 如果你想使用 ref 执行某些操作,但没有特定的事件可以执行此操作,你可能需要一个 effect。我们将在下一页讨论 effect。
-#### Flushing state updates synchronously with flushSync {/*flushing-state-updates-synchronously-with-flush-sync*/}
+#### 用 flushSync 同步更新 state {/*flushing-state-updates-synchronously-with-flush-sync*/}
-Consider code like this, which adds a new todo and scrolls the screen down to the last child of the list. Notice how, for some reason, it always scrolls to the todo that was *just before* the last added one:
+思考这样的代码,它添加一个新的待办事项,并将屏幕向下滚动到列表的最后一个子项。请注意,出于某种原因,它总是滚动到最后一个添加*之前* 的待办事项:
@@ -526,7 +528,7 @@ export default function TodoList() {
return (
<>
- Add
+ 添加
-The issue is with these two lines:
+问题出在这两行:
```js
setTodos([ ...todos, newTodo]);
listRef.current.lastChild.scrollIntoView();
```
-In React, [state updates are queued.](/learn/queueing-a-series-of-state-updates) Usually, this is what you want. However, here it causes a problem because `setTodos` does not immediately update the DOM. So the time you scroll the list to its last element, the todo has not yet been added. This is why scrolling always "lags behind" by one item.
+在 React 中,[state 更新是排队进行的](/learn/queueing-a-series-of-state-updates)。通常,这就是你想要的。但是,在这个示例中会导致问题,因为 `setTodos` 不会立即更新 DOM。因此,当你将列表滚动到最后一个元素时,尚未添加待办事项。这就是为什么滚动总是“落后”一项的原因。
-To fix this issue, you can force React to update ("flush") the DOM synchronously. To do this, import `flushSync` from `react-dom` and **wrap the state update** into a `flushSync` call:
+要解决此问题,你可以强制 React 同步更新(“刷新”)DOM。 为此,从 `react-dom` 导入 `flushSync` 并**将 state 更新包裹** 到 `flushSync` 调用中:
```js
flushSync(() => {
@@ -571,7 +573,7 @@ flushSync(() => {
listRef.current.lastChild.scrollIntoView();
```
-This will instruct React to update the DOM synchronously right after the code wrapped in `flushSync` executes. As a result, the last todo will already be in the DOM by the time you try to scroll to it:
+这将指示 React 当封装在 `flushSync` 中的代码执行后,立即同步更新 DOM。因此,当你尝试滚动到最后一个待办事项时,它已经在 DOM 中了:
@@ -601,7 +603,7 @@ export default function TodoList() {
return (
<>
- Add
+ 添加
-## Best practices for DOM manipulation with refs {/*best-practices-for-dom-manipulation-with-refs*/}
+## 使用 refs 操作 DOM 的最佳实践 {/*best-practices-for-dom-manipulation-with-refs*/}
-Refs are an escape hatch. You should only use them when you have to "step outside React". Common examples of this include managing focus, scroll position, or calling browser APIs that React does not expose.
+Refs 是一个应急方案。你应该只在你必须“跳出 React”时使用它们。这方面的常见示例包括管理焦点、滚动位置或调用 React 未暴露的浏览器 API。
-If you stick to non-destructive actions like focusing and scrolling, you shouldn't encounter any problems. However, if you try to **modify** the DOM manually, you can risk conflicting with the changes React is making.
+如果你坚持聚焦和滚动等非破坏性操作,应该不会遇到任何问题。但是,如果你尝试手动**修改** DOM,则可能会与 React 所做的更改发生冲突。
-To illustrate this problem, this example includes a welcome message and two buttons. The first button toggles its presence using [conditional rendering](/learn/conditional-rendering) and [state](/learn/state-a-components-memory), as you would usually do in React. The second button uses the [`remove()` DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Element/remove) to forcefully remove it from the DOM outside of React's control.
+为了说明这个问题,这个例子包括一条欢迎消息和两个按钮。第一个按钮使用 [条件渲染](/learn/conditional-rendering) 和 [state](/learn/state-a-components-memory) 切换它的显示和隐藏,就像你通常在 React 中所做的那样。第二个按钮使用 [`remove()` DOM API](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/remove) 将其从 React 控制之外的 DOM 中强行移除.
-Try pressing "Toggle with setState" a few times. The message should disappear and appear again. Then press "Remove from the DOM". This will forcefully remove it. Finally, press "Toggle with setState":
+尝试按几次“通过 setState 切换”。该消息会消失并再次出现。然后按 “从 DOM 中删除”。这将强行删除它。最后,按 “通过 setState 切换”:
@@ -655,13 +657,13 @@ export default function Counter() {
onClick={() => {
setShow(!show);
}}>
- Toggle with setState
+ 通过 setState 切换
{
ref.current.remove();
}}>
- Remove from the DOM
+ 从 DOM 中删除
{show && Hello world
}
@@ -679,20 +681,20 @@ button {
-After you've manually removed the DOM element, trying to use `setState` to show it again will lead to a crash. This is because you've changed the DOM, and React doesn't know how to continue managing it correctly.
+在你手动删除 DOM 元素后,尝试使用 `setState` 再次显示它会导致崩溃。这是因为你更改了 DOM,而 React 不知道如何继续正确管理它。
-**Avoid changing DOM nodes managed by React.** Modifying, adding children to, or removing children from elements that are managed by React can lead to inconsistent visual results or crashes like above.
+**避免更改由 React 管理的 DOM 节点。** 对 React 管理的元素进行修改、添加子元素、从中删除子元素会导致不一致的视觉结果,或与上述类似的崩溃。
-However, this doesn't mean that you can't do it at all. It requires caution. **You can safely modify parts of the DOM that React has _no reason_ to update.** For example, if some `
` is always empty in the JSX, React won't have a reason to touch its children list. Therefore, it is safe to manually add or remove elements there.
+但是,这并不意味着你完全不能这样做。它需要谨慎。 **你可以安全地修改 React _没有理由_ 更新的部分 DOM。** 例如,如果某些 `
` 在 JSX 中始终为空,React 将没有理由去变动其子列表。 因此,在那里手动增删元素是安全的。
-- Refs are a generic concept, but most often you'll use them to hold DOM elements.
-- You instruct React to put a DOM node into `myRef.current` by passing ``.
-- Usually, you will use refs for non-destructive actions like focusing, scrolling, or measuring DOM elements.
-- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using `forwardRef` and passing the second `ref` argument down to a specific node.
-- Avoid changing DOM nodes managed by React.
-- If you do modify DOM nodes managed by React, modify parts that React has no reason to update.
+- Refs 是一个通用概念,但大多数情况下你会使用它们来保存 DOM 元素。
+- 你通过传递 `
` 指示 React 将 DOM 节点放入 `myRef.current`。
+- 通常,你会将 refs 用于非破坏性操作,例如聚焦、滚动或测量 DOM 元素。
+- 默认情况下,组件不暴露其 DOM 节点。 您可以通过使用 `forwardRef` 并将第二个 `ref` 参数传递给特定节点来暴露 DOM 节点。
+- 避免更改由 React 管理的 DOM 节点。
+- 如果你确实修改了 React 管理的 DOM 节点,请修改 React 没有理由更新的部分。
@@ -700,9 +702,9 @@ However, this doesn't mean that you can't do it at all. It requires caution. **Y
-#### Play and pause the video {/*play-and-pause-the-video*/}
+#### 播放和暂停视频 {/*play-and-pause-the-video*/}
-In this example, the button toggles a state variable to switch between a playing and a paused state. However, in order to actually play or pause the video, toggling state is not enough. You also need to call [`play()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play) and [`pause()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause) on the DOM element for the ``. Add a ref to it, and make the button work.
+在此示例中,按钮切换 state 变量以在播放和暂停状态之间切换。 然而,为了实际播放或暂停视频,切换状态是不够的。你还需要在 `` 的 DOM 元素上调用 [`play()`](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement/play) 和 [`pause()`](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement/pause)。 向它添加一个 ref,并使按钮起作用。
@@ -720,7 +722,7 @@ export default function VideoPlayer() {
return (
<>
- {isPlaying ? 'Pause' : 'Play'}
+ {isPlaying ? '暂停' : '播放'}
-For an extra challenge, keep the "Play" button in sync with whether the video is playing even if the user right-clicks the video and plays it using the built-in browser media controls. You might want to listen to `onPlay` and `onPause` on the video to do that.
+对于额外的挑战,即使用户右键单击视频并使用内置浏览器媒体控件播放,也要使“播放”按钮与视频是否正在播放同步。 您可能需要在视频中监听 `onPlay` 和 `onPause` 才能做到这一点。
-Declare a ref and put it on the `` element. Then call `ref.current.play()` and `ref.current.pause()` in the event handler depending on the next state.
+声明一个 ref 并将其放在 `` 元素上。然后根据下一个 state 在事件处理器中调用 `ref.current.play()` 和 `ref.current.pause()`。
@@ -768,7 +770,7 @@ export default function VideoPlayer() {
return (
<>
- {isPlaying ? 'Pause' : 'Play'}
+ {isPlaying ? '暂停' : '播放'}
-In order to handle the built-in browser controls, you can add `onPlay` and `onPause` handlers to the `` element and call `setIsPlaying` from them. This way, if the user plays the video using the browser controls, the state will adjust accordingly.
+为了处理内置浏览器控件,您可以将 `onPlay` 和 `onPause` 处理程序添加到 `` 元素,并调用它们的 `setIsPlaying`。 这样,如果用户使用浏览器控件播放视频,状态将相应调整。
-#### Focus the search field {/*focus-the-search-field*/}
+#### 使搜索域获得焦点 {/*focus-the-search-field*/}
-Make it so that clicking the "Search" button puts focus into the field.
+做到单击“搜索”按钮时,使搜索域获得焦点。
@@ -807,10 +809,10 @@ export default function Page() {
return (
<>
- Search
+ 搜索
>
);
@@ -825,7 +827,7 @@ button { display: block; margin-bottom: 10px; }
-Add a ref to the input, and call `focus()` on the DOM node to focus it:
+向输入框添加一个 ref,并在 DOM 节点上调用 `focus()` 以使其获得焦点:
@@ -840,12 +842,12 @@ export default function Page() {
{
inputRef.current.focus();
}}>
- Search
+ 搜索
>
);
@@ -860,9 +862,9 @@ button { display: block; margin-bottom: 10px; }
-#### Scrolling an image carousel {/*scrolling-an-image-carousel*/}
+#### 滚动图像轮播 {/*scrolling-an-image-carousel*/}
-This image carousel has a "Next" button that switches the active image. Make the gallery scroll horizontally to the active image on click. You will want to call [`scrollIntoView()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) on the DOM node of the active image:
+此图像轮播有一个“下一个”按钮,可以切换激活的图像。单击时使图库水平滚动到激活的图像。你需要在激活的图像的 DOM 节点上调用 [`scrollIntoView()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView):
```js
node.scrollIntoView({
@@ -874,7 +876,7 @@ node.scrollIntoView({
-You don't need to have a ref to every image for this exercise. It should be enough to have a ref to the currently active image, or to the list itself. Use `flushSync` to ensure the DOM is updated *before* you scroll.
+在本练习中,你不需要对每个图像都添加 ref。对当前激活的图像或图像列表本身有一个 ref 就足够了。使用 `flushSync` 确保 DOM 在滚动 *之前* 更新。
@@ -895,7 +897,7 @@ export default function CatFriends() {
setIndex(0);
}
}}>
- Next
+ 下一个
@@ -909,7 +911,7 @@ export default function CatFriends() {
''
}
src={cat.imageUrl}
- alt={'Cat #' + cat.id}
+ alt={'猫猫 #' + cat.id}
/>
))}
@@ -969,15 +971,15 @@ img {
-You can declare a `selectedRef`, and then pass it conditionally only to the current image:
+你可以声明一个 `selectedRef`,然后根据条件将它传递给当前图像:
```js
```
-When `index === i`, meaning that the image is the selected one, the ` ` will receive the `selectedRef`. React will make sure that `selectedRef.current` always points at the correct DOM node.
+当`index === i`时,表示图像是被选中的图像,相应的 ` ` 将接收到 `selectedRef`。React 将确保 `selectedRef.current` 始终指向正确的 DOM 节点。
-Note that the `flushSync` call is necessary to force React to update the DOM before the scroll. Otherwise, `selectedRef.current` would always point at the previously selected item.
+请注意,为了强制 React 在滚动前更新 DOM,`flushSync` 调用是必需的。否则,`selectedRef.current`将始终指向之前选择的项目。
@@ -1006,7 +1008,7 @@ export default function CatFriends() {
inline: 'center'
});
}}>
- Next
+ 下一步
@@ -1026,7 +1028,7 @@ export default function CatFriends() {
: ''
}
src={cat.imageUrl}
- alt={'Cat #' + cat.id}
+ alt={'猫猫 #' + cat.id}
/>
))}
@@ -1086,13 +1088,13 @@ img {
-#### Focus the search field with separate components {/*focus-the-search-field-with-separate-components*/}
+#### 使分开的组件中的搜索域获得焦点 {/*focus-the-search-field-with-separate-components*/}
-Make it so that clicking the "Search" button puts focus into the field. Note that each component is defined in a separate file and shouldn't be moved out of it. How do you connect them together?
+做到单击“搜索”按钮将焦点放在搜索域上。请注意,每个组件都在单独的文件中定义,并且不能将其移出。如何将它们连接在一起?
-You'll need `forwardRef` to opt into exposing a DOM node from your own component like `SearchInput`.
+你需要 `forwardRef` 来主动从你自己的组件中暴露一个 DOM 节点,比如 `SearchInput`。
@@ -1118,7 +1120,7 @@ export default function Page() {
export default function SearchButton() {
return (
- Search
+ 搜索
);
}
@@ -1128,7 +1130,7 @@ export default function SearchButton() {
export default function SearchInput() {
return (
);
}
@@ -1142,7 +1144,7 @@ button { display: block; margin-bottom: 10px; }
-You'll need to add an `onClick` prop to the `SearchButton`, and make the `SearchButton` pass it down to the browser ``. You'll also pass a ref down to ``, which will forward it to the real ` ` and populate it. Finally, in the click handler, you'll call `focus` on the DOM node stored inside that ref.
+你需要向 `SearchButton` 添加一个`onClick` 属性,`SearchButton` 会将其向下传递给浏览器原生 ``。你还要向下传递一个 ref 给 ``,`` 将转发 ref 给真正的 ` ` 并对它进行赋值。最后,在单击事件处理器中,你将能对存储在该 ref 中的 DOM 节点调用 `focus`。
@@ -1170,7 +1172,7 @@ export default function Page() {
export default function SearchButton({ onClick }) {
return (
- Search
+ 搜索
);
}
@@ -1184,7 +1186,7 @@ export default forwardRef(
return (
);
}