Skip to content

Commit

Permalink
docs(cn): translate reference/react/cloneElement into Chinese (#1207)
Browse files Browse the repository at this point in the history
Co-authored-by: Yucohny <yucohny@163.com>
  • Loading branch information
li-jia-nan and Yucohny authored Jun 27, 2023
1 parent 815a2c1 commit 125770b
Showing 1 changed file with 56 additions and 56 deletions.
112 changes: 56 additions & 56 deletions src/content/reference/react/cloneElement.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ title: cloneElement

<Pitfall>

Using `cloneElement` is uncommon and can lead to fragile code. [See common alternatives.](#alternatives)
使用 `cloneElement` 并不常见,并且可能会导致代码变得脆弱。[查看常见的替代方案](#alternatives)

</Pitfall>

<Intro>

`cloneElement` lets you create a new React element using another element as a starting point.
`cloneElement` 允许你使用一个元素作为初始值创建一个新的 React 元素。

```js
const clonedElement = cloneElement(element, props, ...children)
Expand All @@ -22,11 +22,11 @@ const clonedElement = cloneElement(element, props, ...children)

---

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

### `cloneElement(element, props, ...children)` {/*cloneelement*/}

Call `cloneElement` to create a React element based on the `element`, but with different `props` and `children`:
调用 `cloneElement` 方法会基于 `element` 创建一个新的 React 元素,但新元素具有不同的 `props` `children`

```js
import { cloneElement } from 'react';
Expand All @@ -43,42 +43,42 @@ const clonedElement = cloneElement(
console.log(clonedElement); // <Row title="Cabbage">Goodbye</Row>
```

[See more examples below.](#usage)
[请参阅下面的更多示例](#usage)

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

* `element`: The `element` argument must be a valid React element. For example, it could be a JSX node like `<Something />`, the result of calling [`createElement`](/reference/react/createElement), or the result of another `cloneElement` call.
* `element``element` 参数必须是一个有效的 React 元素。例如,它可以是一个类似 `<Something />` 这样的 JSX 节点,也可以是 [`createElement`](/reference/react/createElement) 调用的结果,或者也可以是另一个 `cloneElement` 调用的结果。

* `props`: The `props` argument must either be an object or `null`. If you pass `null`, the cloned element will retain all of the original `element.props`. Otherwise, for every prop in the `props` object, the returned element will "prefer" the value from `props` over the value from `element.props`. The rest of the props will be filled from the original `element.props`. If you pass `props.key` or `props.ref`, they will replace the original ones.
* `props``props` 参数必须是一个对象或 `null`。如果传 `null`,克隆后的元素将保留所有原始的 `element.props`。否则,对于 `props` 对象中的每个 prop 属性,返回的元素将“优先”使用 `props` 中的值而不是 `element.props` 中的值。其余的 props 将从原始的 `element.props` 中填充。如果你传递 `props.key` 或者 `props.ref`,它们将替换原来的。

* **optional** `...children`: Zero or more child nodes. They can be any React nodes, including React elements, strings, numbers, [portals](/reference/react-dom/createPortal), empty nodes (`null`, `undefined`, `true`, and `false`), and arrays of React nodes. If you don't pass any `...children` arguments, the original `element.props.children` will be preserved.
* **可选** `...children`:零个或多个子节点。它们可以是任何 React 节点,包括 React 元素、字符串、数字、[portals](/reference/react-dom/createPortal)、空节点(`null``undefined``true` `false`),和 React 元素数组。如果你不传递任何 `...children` 参数,则原始的 `element.props.children` 将被保留。

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

`cloneElement` returns a React element object with a few properties:
`cloneElement` 返回一个具有一些属性的 React element 对象:

* `type`: Same as `element.type`.
* `props`: The result of shallowly merging `element.props` with the overriding `props` you have passed.
* `ref`: The original `element.ref`, unless it was overridden by `props.ref`.
* `key`: The original `element.key`, unless it was overridden by `props.key`.
* `type`:与 `element.type` 相同。
* `props`:将 `element.props` 与你传递的 `props` 浅合并的结果。
* `ref`:原始的 `element.ref`,除非它被 `props.ref` 覆盖。
* `key`:原始的 `element.key`,除非它被 `props.key` 覆盖。

Usually, you'll return the element from your component or make it a child of another element. Although you may read the element's properties, it's best to treat every element as opaque after it's created, and only render it.
通常,你将从组件返回该元素或使其成为另一个元素的子元素。尽管你可以读取元素的属性,但最好在创建每个元素后将其视为不透明的,并且仅渲染它。

#### Caveats {/*caveats*/}
#### 注意事项 {/*caveats*/}

* Cloning an element **does not modify the original element.**
* 克隆一个元素 **不会修改原始元素**

* You should only **pass children as multiple arguments to `cloneElement` if they are all statically known,** like `cloneElement(element, null, child1, child2, child3)`. If your children are dynamic, pass the entire array as the third argument: `cloneElement(element, null, listItems)`. This ensures that React will [warn you about missing `key`s](/learn/rendering-lists#keeping-list-items-in-order-with-key) for any dynamic lists. For static lists this is not necessary because they never reorder.
* 如果已知 children 是静态的,则你应该 **将它们作为多个参数传递给 `cloneElement`**,例如 `cloneElement(element, null, child1, child2, child3)`。如果你的 children 是动态的,请将整个数组作为第三个参数传递:`cloneElement(element, null, listItems)`。这确保了 React 会对任何动态列表 [警告你缺少“key](/learn/rendering-lists#keeping-list-items-in-order-with-key),对于静态的列表,这是不必要的,因为它们不会重新排序。

* `cloneElement` makes it harder to trace the data flow, so **try the [alternatives](#alternatives) instead.**
* `cloneElement` 会使得跟踪数据流向变得更加困难,所以请 **尝试使用 [替代方案](#alternatives)**

---

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

### Overriding props of an element {/*overriding-props-of-an-element*/}
### 覆盖元素的 props {/*overriding-props-of-an-element*/}

To override the props of some <CodeStep step={1}>React element</CodeStep>, pass it to `cloneElement` with the <CodeStep step={2}>props you want to override</CodeStep>:
要覆盖某些 <CodeStep step={1}>React element</CodeStep> 的 props,请将其与 <CodeStep step={2}>要覆盖的 props</CodeStep> 一起传递给 `cloneElement`

```js [[1, 5, "<Row title=\\"Cabbage\\" />"], [2, 6, "{ isHighlighted: true }"], [3, 4, "clonedElement"]]
import { cloneElement } from 'react';
Expand All @@ -90,11 +90,11 @@ const clonedElement = cloneElement(
);
```

Here, the resulting <CodeStep step={3}>cloned element</CodeStep> will be `<Row title="Cabbage" isHighlighted={true} />`.
在这里,生成的 <CodeStep step={3}>克隆 element</CodeStep> 将为 `<Row title="Cabbage" isHighlighted={true} />`

**Let's walk through an example to see when it's useful.**
**让我们看一个示例,看看它什么时候有用**

Imagine a `List` component that renders its [`children`](/learn/passing-props-to-a-component#passing-jsx-as-children) as a list of selectable rows with a "Next" button that changes which row is selected. The `List` component needs to render the selected `Row` differently, so it clones every `<Row>` child that it has received, and adds an extra `isHighlighted: true` or `isHighlighted: false` prop:
想象一个 `List` 组件将其 [`children`](/learn/passing-props-to-a-component#passing-jsx-as-children) 渲染为可选择行的列表,并带有可更改的“下一步”按钮选择了哪一行。`List` 组件需要以不同的方式渲染所选的 `Row`,因此它克隆它收到的每个 `<Row>` 子级,并添加额外的 `isHighlighted: true` `isHighlighted: false` 属性:

```js {6-8}
export default function List({ children }) {
Expand All @@ -108,7 +108,7 @@ export default function List({ children }) {
)}
```
Let's say the original JSX received by `List` looks like this:
假设 `List` 收到的原始 JSX 如下所示:
```js {2-4}
<List>
Expand All @@ -118,7 +118,7 @@ Let's say the original JSX received by `List` looks like this:
</List>
```
By cloning its children, the `List` can pass extra information to every `Row` inside. The result looks like this:
通过克隆其 children`List` 可以将额外的信息传递给内部的每个 `Row`。结果如下:
```js {4,8,12}
<List>
Expand All @@ -137,7 +137,7 @@ By cloning its children, the `List` can pass extra information to every `Row` in
</List>
```
Notice how pressing "Next" updates the state of the `List`, and highlights a different row:
注意点击“下一步”如何更新 `List` 的状态,并高亮显示不同的行:
<Sandpack>
Expand Down Expand Up @@ -178,7 +178,7 @@ export default function List({ children }) {
(i + 1) % Children.count(children)
);
}}>
Next
下一步
</button>
</div>
);
Expand Down Expand Up @@ -232,21 +232,21 @@ button {
</Sandpack>
To summarize, the `List` cloned the `<Row />` elements it received and added an extra prop to them.
总而言之,`List` 克隆了它接收的 `<Row />` 元素,并向它们添加额外的 props。
<Pitfall>
Cloning children makes it hard to tell how the data flows through your app. Try one of the [alternatives.](#alternatives)
克隆 children 使得你很难判断数据如何流经你的应用。尝试一种 [替代方案](#alternatives)
</Pitfall>
---
## Alternatives {/*alternatives*/}
## 替代方案 {/*alternatives*/}
### Passing data with a render prop {/*passing-data-with-a-render-prop*/}
### 通过 props 传递数据 {/*passing-data-with-a-render-prop*/}
Instead of using `cloneElement`, consider accepting a *render prop* like `renderItem`. Here, `List` receives `renderItem` as a prop. `List` calls `renderItem` for every item and passes `isHighlighted` as an argument:
接受类似 `renderItem` 这样的 *render prop* 代替 `cloneElement` 的用法。在这里,`List` 接收 `renderItem` 作为 props。`List` 为数组每一项调用 `renderItem`,并传递 `isHighlighted` 作为参数:
```js {1,7}
export default function List({ items, renderItem }) {
Expand All @@ -259,7 +259,7 @@ export default function List({ items, renderItem }) {
})}
```
The `renderItem` prop is called a "render prop" because it's a prop that specifies how to render something. For example, you can pass a `renderItem` implementation that renders a `<Row>` with the given `isHighlighted` value:
`renderItem` 属性称为“渲染属性”,因为它是决定如何渲染某些内容的属性。例如,你可以传递一个 `renderItem` 实现使用给定的 `isHighlighted` 值呈现 `<Row>`
```js {3,7}
<List
Expand All @@ -274,7 +274,7 @@ The `renderItem` prop is called a "render prop" because it's a prop that specifi
/>
```
The end result is the same as with `cloneElement`:
最终结果与 `cloneElement` 相同:
```js {4,8,12}
<List>
Expand All @@ -293,7 +293,7 @@ The end result is the same as with `cloneElement`:
</List>
```
However, you can clearly trace where the `isHighlighted` value is coming from.
但是你可以清楚地追踪 `isHighlighted` 的来源。
<Sandpack>
Expand Down Expand Up @@ -335,7 +335,7 @@ export default function List({ items, renderItem }) {
(i + 1) % items.length
);
}}>
Next
下一步
</button>
</div>
);
Expand Down Expand Up @@ -389,22 +389,22 @@ button {
</Sandpack>
This pattern is preferred to `cloneElement` because it is more explicit.
这种方案优于 `cloneElement`,因为它更加清晰。
---
### Passing data through context {/*passing-data-through-context*/}
### 通过 context 传递数据 {/*passing-data-through-context*/}
Another alternative to `cloneElement` is to [pass data through context.](/learn/passing-data-deeply-with-context)
`cloneElement` 的另一种替代方法是 [通过 context 传递数据](/learn/passing-data-deeply-with-context)
For example, you can call [`createContext`](/reference/react/createContext) to define a `HighlightContext`:
例如,你可以调用 [`createContext`](/reference/react/createContext) 来定义一个 `HighlightContext`
```js
export const HighlightContext = createContext(false);
```
Your `List` component can wrap every item it renders into a `HighlightContext` provider:
`List` 组件可以将其呈现的每个 item 传递到 `HighlightContext` provider 中:
```js {8,10}
export default function List({ items, renderItem }) {
Expand All @@ -421,15 +421,15 @@ export default function List({ items, renderItem }) {
})}
```
With this approach, `Row` does not need to receive an `isHighlighted` prop at all. Instead, it reads the context:
通过这种方法,`Row` 不需要接收 `isHighlighted`属性,因为它可以从 context 中读取:
```js Row.js {2}
export default function Row({ title }) {
const isHighlighted = useContext(HighlightContext);
// ...
```
This allows the calling component to not know or worry about passing `isHighlighted` to `<Row>`:
这允许调用组件时无需关心是否将 `isHighlighted` 传递给了 `<Row>`
```js {4}
<List
Expand All @@ -440,7 +440,7 @@ This allows the calling component to not know or worry about passing `isHighligh
/>
```
Instead, `List` and `Row` coordinate the highlighting logic through context.
相反,`List` `Row` 通过上下文协调突出显示逻辑。
<Sandpack>
Expand Down Expand Up @@ -486,7 +486,7 @@ export default function List({ items, renderItem }) {
(i + 1) % items.length
);
}}>
Next
下一步
</button>
</div>
);
Expand Down Expand Up @@ -550,13 +550,13 @@ button {
</Sandpack>
[Learn more about passing data through context.](/reference/react/useContext#passing-data-deeply-into-the-tree)
[了解有关通过 context 传递数据的更多信息](/reference/react/useContext#passing-data-deeply-into-the-tree)
---
### Extracting logic into a custom Hook {/*extracting-logic-into-a-custom-hook*/}
### 将逻辑提取到自定义 Hook {/*extracting-logic-into-a-custom-hook*/}
Another approach you can try is to extract the "non-visual" logic into your own Hook, and use the information returned by your Hook to decide what to render. For example, you could write a `useList` custom Hook like this:
你可以尝试的另一种方法是将“非视觉”部分的逻辑提取到你的自定义 Hook 中,并使用 Hook 的返回值来决定渲染什么。例如,你可以编写一个 `useList` 自定义 Hook,如下所示:
```js
import { useState } from 'react';
Expand All @@ -575,7 +575,7 @@ export default function useList(items) {
}
```
Then you could use it like this:
然后你可以像这样使用它:
```js {2,9,13}
export default function App() {
Expand All @@ -591,14 +591,14 @@ export default function App() {
)}
<hr />
<button onClick={onNext}>
Next
下一步
</button>
</div>
);
}
```
The data flow is explicit, but the state is inside the `useList` custom Hook that you can use from any component:
数据流是显式的,但状态位于 `useList` 自定义 Hook 内,你可以在任意一个组件内使用它:
<Sandpack>
Expand All @@ -620,7 +620,7 @@ export default function App() {
)}
<hr />
<button onClick={onNext}>
Next
下一步
</button>
</div>
);
Expand Down Expand Up @@ -691,4 +691,4 @@ button {
</Sandpack>
This approach is particularly useful if you want to reuse this logic between different components.
如果你想在不同组件之间复用此逻辑,则这个方案十分有用。

0 comments on commit 125770b

Please sign in to comment.