Skip to content

Commit

Permalink
docs(cn): translate reference/react/forwardRef into Chinese (#1147)
Browse files Browse the repository at this point in the history
Co-authored-by: Xavi Lee <awxiaoxian2020@163.com>
Co-authored-by: Yucohny <79147654+Yucohny@users.noreply.github.com>
Co-authored-by: Xleine <919143384@qq.com>
  • Loading branch information
4 people authored Jun 10, 2023
1 parent b9ee255 commit 0d6e5d3
Showing 1 changed file with 47 additions and 46 deletions.
93 changes: 47 additions & 46 deletions src/content/reference/react/forwardRef.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: forwardRef

<Intro>

`forwardRef` lets your component expose a DOM node to parent component with a [ref.](/learn/manipulating-the-dom-with-refs)
`forwardRef` 允许你的组件使用 [ref](/learn/manipulating-the-dom-with-refs) 将一个 DOM 节点暴露给父组件。

```js
const SomeComponent = forwardRef(render)
Expand All @@ -16,11 +16,11 @@ const SomeComponent = forwardRef(render)

---

## Reference {/*reference*/}
## 参考 {/*reference*/}

### `forwardRef(render)` {/*forwardref*/}

Call `forwardRef()` to let your component receive a ref and forward it to a child component:
使用 `forwardRef()` 来让你的组件接收一个 ref 并将其传递给一个子组件:

```js
import { forwardRef } from 'react';
Expand All @@ -30,26 +30,26 @@ const MyInput = forwardRef(function MyInput(props, ref) {
});
```

[See more examples below.](#usage)
[请看下面的更多例子](#usage)

#### Parameters {/*parameters*/}
#### 参数 {/*parameters*/}

* `render`: The render function for your component. React calls this function with the props and `ref` that your component received from its parent. The JSX you return will be the output of your component.
* `render`:组件的渲染函数。React 会调用该函数并传入父组件传递来的参数和 `ref`。返回的 JSX 将成为组件的输出。

#### Returns {/*returns*/}
#### 返回值 {/*returns*/}

`forwardRef` returns a React component that you can render in JSX. Unlike React components defined as plain functions, a component returned by `forwardRef` is also able to receive a `ref` prop.
`forwardRef` 返回一个可以在 JSX 中渲染的 React 组件。与作为纯函数定义的 React 组件不同,`forwardRef` 返回的组件还能够接收 `ref` 属性。

#### Caveats {/*caveats*/}
#### 警告 {/*caveats*/}

* In Strict Mode, React will **call your render 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. If your render function is pure (as it should be), this should not affect the logic of your component. The result from one of the calls will be ignored.
* 在严格模式中,为了 [帮助你找到意外的副作用](#my-initializer-or-updater-function-runs-twice),React 将会 **调用两次你的渲染函数**。不过这仅限于开发环境,并不会影响生产环境。如果你的渲染函数是纯函数(也应该是),这应该不会影响你的组件逻辑。其中一个调用的结果将被忽略。


---

### `render` function {/*render-function*/}
### `render` 函数 {/*render-function*/}

`forwardRef` accepts a render function as an argument. React calls this function with `props` and `ref`:
`forwardRef` 接受一个渲染函数作为参数。React 将会使用 `props` `ref` 调用此函数:

```js
const MyInput = forwardRef(function MyInput(props, ref) {
Expand All @@ -62,23 +62,23 @@ const MyInput = forwardRef(function MyInput(props, ref) {
});
```

#### Parameters {/*render-parameters*/}
#### 参数 {/*render-parameters*/}

* `props`: The props passed by the parent component.
* `props`:父组件传递过来的参数。

* `ref`: The `ref` attribute passed by the parent component. The `ref` can be an object or a function. If the parent component has not passed a ref, it will be `null`. You should either pass the `ref` you receive to another component, or pass it to [`useImperativeHandle`.](/reference/react/useImperativeHandle)
* `ref`:父组件传递的 `ref` 属性。`ref` 可以是一个对象或函数。如果父组件没有传递一个 ref,那么它将会是 `null`。你应该将接收到的 `ref` 转发给另一个组件,或者将其传递给 [`useImperativeHandle`](/reference/react/useImperativeHandle)

#### Returns {/*render-returns*/}
#### 返回值 {/*render-returns*/}

`forwardRef` returns a React component that you can render in JSX. Unlike React components defined as plain functions, the component returned by `forwardRef` is able to take a `ref` prop.
`forwardRef` 返回一个可以在 JSX 中渲染的 React 组件。与作为纯函数定义的 React 组件不同,`forwardRef` 返回的组件还能够接收 `ref` 属性。

---

## Usage {/*usage*/}
## 用法 {/*usage*/}

### Exposing a DOM node to the parent component {/*exposing-a-dom-node-to-the-parent-component*/}
### DOM 节点暴露给父组件 {/*exposing-a-dom-node-to-the-parent-component*/}

By default, each component's DOM nodes are private. However, sometimes it's useful to expose a DOM node to the parent--for example, to allow focusing it. To opt in, wrap your component definition into `forwardRef()`:
默认情况下,每个组件的 DOM 节点都是私有的。然而,有时候将 DOM 节点公开给父组件是很有用的,比如允许对它进行聚焦。如果你想将其公开,可以将组件定义包装在 `forwardRef()` 中:

```js {3,11}
import { forwardRef } from 'react';
Expand All @@ -94,7 +94,7 @@ const MyInput = forwardRef(function MyInput(props, ref) {
});
```

You will receive a <CodeStep step={1}>ref</CodeStep> as the second argument after props. Pass it to the DOM node that you want to expose:
你将在 props 之后收到一个 <CodeStep step={1}>ref</CodeStep> 作为第二个参数。将其传递到要公开的 DOM 节点中:

```js {8} [[1, 3, "ref"], [1, 8, "ref", 30]]
import { forwardRef } from 'react';
Expand All @@ -110,7 +110,7 @@ const MyInput = forwardRef(function MyInput(props, ref) {
});
```

This lets the parent `Form` component access the <CodeStep step={2}>`<input>` DOM node</CodeStep> exposed by `MyInput`:
这样,父级的 `Form` 组件就能够访问 `MyInput` 暴露的 <CodeStep step={2}>`<input>` DOM 节点</CodeStep>

```js [[1, 2, "ref"], [1, 10, "ref", 41], [2, 5, "ref.current"]]
function Form() {
Expand All @@ -131,15 +131,15 @@ function Form() {
}
```

This `Form` component [passes a ref](/reference/react/useRef#manipulating-the-dom-with-a-ref) to `MyInput`. The `MyInput` component *forwards* that ref to the `<input>` browser tag. As a result, the `Form` component can access that `<input>` DOM node and call [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus) on it.
`Form` 组件 [ref 传递至](/reference/react/useRef#manipulating-the-dom-with-a-ref) `MyInput``MyInput` 组件将该 ref **转发**`<input>` 浏览器标签。因此,`Form` 组件可以访问该 `<input>` DOM 节点并对其调用 [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus)

Keep in mind that exposing a ref to the DOM node inside your component makes it harder to change your component's internals later. You will typically expose DOM nodes from reusable low-level components like buttons or text inputs, but you won't do it for application-level components like an avatar or a comment.
请记住,将组件内部的 ref 暴露给 DOM 节点会使得在稍后更改组件内部更加困难。通常,你会将 DOM 节点从可重用的低级组件中暴露出来,例如按钮或文本输入框,但不会在应用程序级别的组件中这样做,例如头像或评论。

<Recipes title="Examples of forwarding a ref">

#### Focusing a text input {/*focusing-a-text-input*/}
#### 聚焦文本输入框 {/*focusing-a-text-input*/}

Clicking the button will focus the input. The `Form` component defines a ref and passes it to the `MyInput` component. The `MyInput` component forwards that ref to the browser `<input>`. This lets the `Form` component focus the `<input>`.
点击该按钮将聚焦输入框。`Form` 组件定义了一个 ref 并将其传递到 `MyInput` 组件。`MyInput` 组件将该 ref 转发至浏览器的 `<input>` 标签,这使得 `Form` 组件可以聚焦该 `<input>`

<Sandpack>

Expand Down Expand Up @@ -191,9 +191,9 @@ input {

<Solution />

#### Playing and pausing a video {/*playing-and-pausing-a-video*/}
#### 播放和暂停视频 {/*playing-and-pausing-a-video*/}

Clicking the button will 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. The `App` component defines a ref and passes it to the `MyVideoPlayer` component. The `MyVideoPlayer` component forwards that ref to the browser `<video>` node. This lets the `App` component play and pause the `<video>`.
点击按钮将调用 `<video>` DOM 节点上的 [`play()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play) [`pause()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause) 方法。`App` 组件定义了一个 ref 并将其传递到 `MyVideoPlayer` 组件。`MyVideoPlayer` 组件将该 ref 转发到浏览器的 `<video>` 标签。这使得 `App` 组件可以播放和暂停 `<video>`

<Sandpack>

Expand Down Expand Up @@ -252,9 +252,9 @@ button { margin-bottom: 10px; margin-right: 10px; }

---

### Forwarding a ref through multiple components {/*forwarding-a-ref-through-multiple-components*/}
### 在多个组件中转发 ref {/*forwarding-a-ref-through-multiple-components*/}

Instead of forwarding a `ref` to a DOM node, you can forward it to your own component like `MyInput`:
除了将 `ref` 转发到 DOM 节点外,你还可以将其转发到你自己的组件,例如 `MyInput` 组件:

```js {1,5}
const FormField = forwardRef(function FormField(props, ref) {
Expand All @@ -268,7 +268,7 @@ const FormField = forwardRef(function FormField(props, ref) {
});
```

If that `MyInput` component forwards a ref to its `<input>`, a ref to `FormField` will give you that `<input>`:
如果 `MyInput` 组件将 ref 转发给它的 `<input>`,那么 `FormField` 的 ref 将会获得该 `<input>`

```js {2,5,10}
function Form() {
Expand All @@ -289,7 +289,7 @@ function Form() {
}
```

The `Form` component defines a ref and passes it to `FormField`. The `FormField` component forwards that ref to `MyInput`, which forwards it to a browser `<input>` DOM node. This is how `Form` accesses that DOM node.
`Form` 组件定义了一个 ref 并将其传递给 `FormField``FormField` 组件将该 ref 转发给 `MyInput`,后者又将其转发给浏览器的 `<input>` DOM 节点。这就是 `Form` 获取该 DOM 节点的方式。


<Sandpack>
Expand Down Expand Up @@ -367,9 +367,9 @@ input, button {

---

### Exposing an imperative handle instead of a DOM node {/*exposing-an-imperative-handle-instead-of-a-dom-node*/}
### 暴露一个命令式句柄而不是 DOM 节点 {/*exposing-an-imperative-handle-instead-of-a-dom-node*/}

Instead of exposing an entire DOM node, you can expose a custom object, called an *imperative handle,* with a more constrained set of methods. To do this, you'd need to define a separate ref to hold the DOM node:
可以使用一个被称为 **命令式句柄(imperative handle** 的自定义对象来暴露一个更加受限制的方法集,而不是暴露整个 DOM 节点。为了实现这个目的,你需要定义一个单独的 ref 来存储 DOM 节点:

```js {2,6}
const MyInput = forwardRef(function MyInput(props, ref) {
Expand All @@ -381,7 +381,7 @@ const MyInput = forwardRef(function MyInput(props, ref) {
});
```

Pass the `ref` you received to [`useImperativeHandle`](/reference/react/useImperativeHandle) and specify the value you want to expose to the `ref`:
将收到的 `ref` 传递给 [`useImperativeHandle`](/reference/react/useImperativeHandle) 并指定你想要暴露给 `ref` 的值:

```js {6-15}
import { forwardRef, useRef, useImperativeHandle } from 'react';
Expand All @@ -404,7 +404,7 @@ const MyInput = forwardRef(function MyInput(props, ref) {
});
```

If some component gets a ref to `MyInput`, it will only receive your `{ focus, scrollIntoView }` object instead of the DOM node. This lets you limit the information you expose about your DOM node to the minimum.
如果某个组件得到了 `MyInput` 的 ref,则只会接收到 `{ focus, scrollIntoView }` 对象,而不是整个 DOM 节点。这可以让 DOM 节点暴露的信息限制到最小。

<Sandpack>

Expand All @@ -417,7 +417,7 @@ export default function Form() {

function handleClick() {
ref.current.focus();
// This won't work because the DOM node isn't exposed:
// 这行代码不起作用,因为 DOM 节点没有被暴露出来:
// ref.current.style.opacity = 0.5;
}

Expand Down Expand Up @@ -463,25 +463,26 @@ input {

</Sandpack>

[Read more about using imperative handles.](/reference/react/useImperativeHandle)
[了解更多关于使用命令式句柄的内容](/reference/react/useImperativeHandle)

<Pitfall>

**Do not overuse refs.** You should only use refs for *imperative* behaviors that you can't express as props: for example, scrolling to a node, focusing a node, triggering an animation, selecting text, and so on.
**不要滥用 refs**。只有对于作为 props 无法表达的 **命令式** 行为才应该使用 ref:例如滚动到节点、将焦点放在节点上、触发动画,以及选择文本等等。

**If you can express something as a prop, you should not use a ref.** For example, instead of exposing an imperative handle like `{ open, close }` from a `Modal` component, it is better to take `isOpen` as a prop like `<Modal isOpen={isOpen} />`. [Effects](/learn/synchronizing-with-effects) can help you expose imperative behaviors via props.

**如果可以将某些东西使用 props 表达,那就不应该使用 ref**。例如,不要从一个 Modal 组件中暴露一个命令式的句柄,如 `{ open, close }`,更好的做法是像这样使用 `isOpen` 作为一个像 `<Modal isOpen={isOpen} />`
prop。[Effects](/learn/synchronizing-with-effects) 可以帮助你通过 props 暴露命令式行为。
</Pitfall>

---

## Troubleshooting {/*troubleshooting*/}

### My component is wrapped in `forwardRef`, but the `ref` to it is always `null` {/*my-component-is-wrapped-in-forwardref-but-the-ref-to-it-is-always-null*/}
### 我的组件使用了 `forwardRef`,但是它的 `ref` 总是为 `null` {/*my-component-is-wrapped-in-forwardref-but-the-ref-to-it-is-always-null*/}

This usually means that you forgot to actually use the `ref` that you received.
这通常意味着你忘记实际使用你所接收到的 `ref` 了。

For example, this component doesn't do anything with its `ref`:
例如,这个组件的 `ref` 没有被使用:

```js {1}
const MyInput = forwardRef(function MyInput({ label }, ref) {
Expand All @@ -494,7 +495,7 @@ const MyInput = forwardRef(function MyInput({ label }, ref) {
});
```

To fix it, pass the `ref` down to a DOM node or another component that can accept a ref:
为了修复它,将 `ref` 传递给一个可以接受 `ref` DOM 节点或另一个组件:

```js {1,5}
const MyInput = forwardRef(function MyInput({ label }, ref) {
Expand All @@ -507,7 +508,7 @@ const MyInput = forwardRef(function MyInput({ label }, ref) {
});
```

The `ref` to `MyInput` could also be `null` if some of the logic is conditional:
如果某些逻辑是有条件的,`MyInput``ref` 可能也会为 `null`

```js {1,5}
const MyInput = forwardRef(function MyInput({ label, showInput }, ref) {
Expand All @@ -520,7 +521,7 @@ const MyInput = forwardRef(function MyInput({ label, showInput }, ref) {
});
```

If `showInput` is `false`, then the ref won't be forwarded to any node, and a ref to `MyInput` will remain empty. This is particularly easy to miss if the condition is hidden inside another component, like `Panel` in this example:
如果 `showInput` `false`,则 `ref` 将不会被转发到任何节点,并且 `MyInput` `ref` 会保持为空。如果这个条件隐藏在另一个组件中,那么很容易忽略这一点,比如这个例子中的 `Panel`

```js {5,7}
const MyInput = forwardRef(function MyInput({ label, showInput }, ref) {
Expand Down

0 comments on commit 0d6e5d3

Please sign in to comment.