You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* `initialValue`: The value you want the ref object's`current`property to be initially. It can be a value of any type. This argument is ignored after the initial render.
* `current`: Initially, it's set to the `initialValue` you have passed. You can later set it to something else. If you pass the ref object to React as a `ref`attribute to a JSX node, React will set its `current`property.
On the next renders, `useRef`will return the same object.
46
+
在后续的渲染中,`useRef`将返回同一个对象。
47
47
48
-
#### Caveats {/*caveats*/}
48
+
#### 注意事项 {/*caveats*/}
49
49
50
-
* You can mutate the `ref.current`property. Unlike state, it is mutable. However, if it holds an object that is used for rendering (for example, a piece of your state), then you shouldn't mutate that object.
51
-
* When you change the `ref.current`property, React does not re-render your component. React is not aware of when you change it because a ref is a plain JavaScript object.
52
-
* Do not write _or read_ `ref.current` during rendering, except for [initialization.](#avoiding-recreating-the-ref-contents) This makes your component's behavior unpredictable.
53
-
* In Strict Mode, React will **call your component function twice** in order to [help you find accidental impurities.](#my-initializer-or-updater-function-runs-twice) This is development-only behavior and does not affect production. Each ref object will be created twice, but one of the versions will be discarded. If your component function is pure (as it should be), this should not affect the behavior.
50
+
* 你可以修改 `ref.current`属性。与 state 不同,它是可变的。然而,如果它持有一个用于渲染的对象(例如,你的 state 的一部分),那么你就不应该修改这个对象。
`useRef`returns a <CodeStep step={1}>ref object</CodeStep> with a single <CodeStep step={2}>`current` property</CodeStep> initially set to the <CodeStep step={3}>initial value</CodeStep> you provided.
On the next renders, `useRef`will return the same object. You can change its `current`property to store information and read it later. This might remind you of [state](/reference/react/useState), but there is an important difference.
**Changing a ref does not trigger a re-render.** This means refs are perfect for storing information that doesn't affect the visual output of your component. For example, if you need to store an [interval ID](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) and retrieve it later, you can put it in a ref. To update the value inside the ref, you need to manually change its <CodeStep step={2}>`current`property</CodeStep>:
Later, you can read that interval ID from the ref so that you can call [clear that interval](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval):
- You can **store information** between re-renders (unlike regular variables, which reset on every render).
98
-
- Changing it **does not trigger a re-render** (unlike state variables, which trigger a re-render).
99
-
- The **information is local** to each copy of your component (unlike the variables outside, which are shared).
97
+
- 你可以在重新渲染之间 **存储信息**(不像是普通对象,每次渲染都会重置)。
98
+
- 改变它 **不会触发重新渲染**(不像是 state 变量,会触发重新渲染)。
99
+
- 对于你的组件的每个副本来说,**这些信息都是本地的**(不像是外面的变量,是共享的)。
100
100
101
-
Changing a ref does not trigger a re-render, so refs are not appropriate for storing information you want to display on the screen. Use state for that instead. Read more about [choosing between `useRef`and`useState`.](/learn/referencing-values-with-refs#differences-between-refs-and-state)
<Recipes titleText="Examples of referencing a value with useRef" titleId="examples-value">
104
104
105
-
#### Click counter {/*click-counter*/}
105
+
#### 点击计数器 {/*click-counter*/}
106
106
107
-
This component uses a ref to keep track of how many times the button was clicked. Note that it's okay to use a ref instead of state here because the click count is only read and written in an event handler.
107
+
这个组件使用 ref 来记录按钮被点击的次数。注意,在这里使用 ref 而不是 state 是可以的,因为点击次数只在事件处理程序中被读取和写入。
108
108
109
109
<Sandpack>
110
110
@@ -129,13 +129,13 @@ export default function Counter() {
129
129
130
130
</Sandpack>
131
131
132
-
If you show`{ref.current}` in the JSX, the number won't update on click. This is because setting `ref.current`does not trigger a re-render. Information that's used for rendering should be state instead.
This example uses a combination of state and refs. Both `startTime`and`now`are state variables because they are used for rendering. But we also need to hold an [interval ID](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) so that we can stop the interval on button press. Since the interval ID is not used for rendering, it's appropriate to keep it in a ref, and manually update it.
138
+
这个例子使用了 state 和 ref 的组合。`startTime`和`now`都是 state 变量,因为它们是用来渲染的。但是我们还需要持有一个 [interval ID](https://developer.mozilla.org/zh-CN/docs/Web/API/setInterval),这样我们就可以在按下按钮时停止定时器。因为 interval ID 不用于渲染,所以应该把它保存在一个 ref 中,并且手动更新它。
139
139
140
140
<Sandpack>
141
141
@@ -188,57 +188,57 @@ export default function Stopwatch() {
188
188
189
189
<Pitfall>
190
190
191
-
**Do not write _or read_ `ref.current` during rendering.**
191
+
**不要在渲染期间写入 _或者读取_ `ref.current`。**
192
192
193
-
React expects that the body of your component [behaves like a pure function](/learn/keeping-components-pure):
- If the inputs ([props](/learn/passing-props-to-a-component), [state](/learn/state-a-components-memory), and [context](/learn/passing-data-deeply-with-context)) are the same, it should return exactly the same JSX.
196
-
- Calling it in a different order or with different arguments should not affect the results of other calls.
Reading or writing a ref **during rendering** breaks these expectations.
198
+
在 **渲染期间** 读取或写入 ref 会破坏这些预期行为。
199
199
200
200
```js {3-4,6-7}
201
201
functionMyComponent() {
202
202
// ...
203
-
// 🚩 Don't write a ref during rendering
203
+
// 🚩 不要在渲染期间写入 ref
204
204
myRef.current=123;
205
205
// ...
206
-
// 🚩 Don't read a ref during rendering
206
+
// 🚩 不要在渲染期间读取 ref
207
207
return<h1>{myOtherRef.current}</h1>;
208
208
}
209
209
```
210
210
211
-
You can read or write refs **from event handlers or effects instead**.
211
+
你可以在 **事件处理程序或者 effects** 中读取和写入 ref。
212
212
213
213
```js {4-5,9-10}
214
214
functionMyComponent() {
215
215
// ...
216
216
useEffect(() => {
217
-
// ✅ You can read or write refs in effects
217
+
// ✅ 你可以在 effects 中读取和写入 ref
218
218
myRef.current=123;
219
219
});
220
220
// ...
221
221
functionhandleClick() {
222
-
// ✅ You can read or write refs in event handlers
222
+
// ✅ 你可以在事件处理程序中读取和写入 ref
223
223
doSomething(myOtherRef.current);
224
224
}
225
225
// ...
226
226
}
227
227
```
228
228
229
-
If you *have to* read [or write](/reference/react/useState#storing-information-from-previous-renders) something during rendering, [use state](/reference/react/useState) instead.
When you break these rules, your component might still work, but most of the newer features we're adding to React will rely on these expectations. Read more about [keeping your components pure.](/learn/keeping-components-pure#where-you-can-cause-side-effects)
### Manipulating the DOM with a ref {/*manipulating-the-dom-with-a-ref*/}
237
+
### 通过 ref 操作 DOM {/*manipulating-the-dom-with-a-ref*/}
238
238
239
-
It's particularly common to use a ref to manipulate the [DOM.](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API) React has built-in support for this.
Then pass your ref object as the `ref`attribute to the JSX of the DOM node you want to manipulate:
251
+
然后将你的 ref 对象作为 `ref`属性传递给你想要操作的 DOM 节点的 JSX:
252
252
253
253
```js [[1, 2, "inputRef"]]
254
254
// ...
255
255
return<input ref={inputRef} />;
256
256
```
257
257
258
-
After React creates the DOM node and puts it on the screen, React will set the <CodeStep step={2}>`current`property</CodeStep> of your ref object to that DOM node. Now you can access the `<input>`'s DOM node and call methods like [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus):
258
+
当 React 创建 DOM 节点并将其渲染到屏幕时,React 将会把 DOM 节点设置为你的 ref 对象的 <CodeStep step={2}>`current`属性</CodeStep>。现在你可以访问 `<input>` 的 DOM 节点,并且可以调用类似于 [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) 的方法:
259
259
260
260
```js [[2, 2, "inputRef.current"]]
261
261
functionhandleClick() {
262
262
inputRef.current.focus();
263
263
}
264
264
```
265
265
266
-
React will set the `current`property back to `null` when the node is removed from the screen.
266
+
当节点从屏幕上移除时,React 将把 `current`属性设回 `null`。
267
267
268
-
Read more about [manipulating the DOM with refs.](/learn/manipulating-the-dom-with-refs)
<Recipes titleText="Examples of manipulating the DOM with useRef" titleId="examples-dom">
271
271
272
-
#### Focusing a text input {/*focusing-a-text-input*/}
272
+
#### 聚焦文字输入框 {/*focusing-a-text-input*/}
273
273
274
-
In this example, clicking the button will focus the input:
274
+
在这个示例中,点击按钮将会聚焦 input:
275
275
276
276
<Sandpack>
277
277
@@ -300,9 +300,9 @@ export default function Form() {
300
300
301
301
<Solution />
302
302
303
-
#### Scrolling an image into view {/*scrolling-an-image-into-view*/}
303
+
#### 滚动图片到视图 {/*scrolling-an-image-into-view*/}
304
304
305
-
In this example, clicking the button will scroll an image into view. It uses a ref to the list DOM node, and then calls DOM [`querySelectorAll`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) API to find the image we want to scroll to.
305
+
在这个示例中,点击按钮将会把图片滚动到视图。这里使用 ref 绑定到列表的 DOM 节点,然后调用 DOM 的 [`querySelectorAll`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/querySelectorAll) API 找到我们想要滚动的图片。
306
306
307
307
<Sandpack>
308
308
@@ -393,9 +393,9 @@ li {
393
393
394
394
<Solution />
395
395
396
-
#### Playing and pausing a video {/*playing-and-pausing-a-video*/}
396
+
#### 播放和暂停视频 {/*playing-and-pausing-a-video*/}
397
397
398
-
This example uses a ref 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 a `<video>` DOM node.
398
+
这个示例使用 ref 调用 `<video>` 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) 方法。
Sometimes, you may want to let the parent component manipulate the DOM inside of your component. For example, maybe you're writing a `MyInput`component, but you want the parent to be able to focus the input (which the parent has no access to). You can use a combination of `useRef`to hold the input and [`forwardRef`](/reference/react/forwardRef) to expose it to the parent component. Read a [detailed walkthrough](/learn/manipulating-the-dom-with-refs#accessing-another-components-dom-nodes) here.
React saves the initial ref value once and ignores it on the next renders.
490
+
React 保存首次的 ref 初始值,并在后续的渲染中忽略它。
491
491
492
492
```js
493
493
functionVideo() {
494
494
constplayerRef=useRef(newVideoPlayer());
495
495
// ...
496
496
```
497
497
498
-
Although the result of `newVideoPlayer()`is only used for the initial render, you're still calling this function on every render. This can be wasteful if it's creating expensive objects.
To solve it, you may initialize the ref like this instead:
500
+
为了解决这个问题,你可以像这样初始化 ref:
501
501
502
502
```js
503
503
functionVideo() {
@@ -508,13 +508,13 @@ function Video() {
508
508
// ...
509
509
```
510
510
511
-
Normally, writing or reading `ref.current`during render is not allowed. However, it's fine in this case because the result is always the same, and the condition only executes during initialization so it's fully predictable.
If you use a type checker and don't want to always check for `null`, you can try a pattern like this instead:
517
+
如果你使用一个类型检查器,并且不想总是检查 `null`,你可以尝试用这样的模式来代替:
518
518
519
519
```js
520
520
functionVideo() {
@@ -532,35 +532,35 @@ function Video() {
532
532
// ...
533
533
```
534
534
535
-
Here, the `playerRef`itself is nullable. However, you should be able to convince your type checker that there is no case in which `getPlayer()`returns`null`. Then use `getPlayer()` in your event handlers.
0 commit comments