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
Copy file name to clipboardexpand all lines: content/docs/render-props.md
+52-53
Original file line number
Diff line number
Diff line change
@@ -4,25 +4,25 @@ title: Render Props
4
4
permalink: docs/render-props.html
5
5
---
6
6
7
-
The term ["render prop"](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce)refers to a technique for sharing code between React components using a prop whose value is a function.
Libraries that use render props include[React Router](https://reacttraining.com/react-router/web/api/Route/render-func)and[Downshift](https://github.com/paypal/downshift).
Components are the primary unit of code reuse in React, but it's not always obvious how to share the state or behavior that one component encapsulates to other components that need that same state.
23
+
组件是 React 代码复用的主要单元,但如何分享一个组件封装到其他需要相同 state 组件的状态或行为并不总是很容易。
24
24
25
-
For example, the following component tracks the mouse position in a web app:
25
+
例如,以下组件跟踪 Web 应用程序中的鼠标位置:
26
26
27
27
```js
28
28
classMouseTrackerextendsReact.Component {
@@ -42,22 +42,22 @@ class MouseTracker extends React.Component {
<p>The current mouse position is ({this.state.x}, {this.state.y})</p>
45
+
<h1>移动鼠标!</h1>
46
+
<p>当前的鼠标位置是 ({this.state.x}, {this.state.y})</p>
47
47
</div>
48
48
);
49
49
}
50
50
}
51
51
```
52
52
53
-
As the cursor moves around the screen, the component displays its (x, y) coordinates in a `<p>`.
53
+
当光标在屏幕上移动时,组件在 `<p>` 中显示其(x,y)坐标。
54
54
55
-
Now the question is: How can we reuse this behavior in another component? In other words, if another component needs to know about the cursor position, can we encapsulate that behavior so that we can easily share it with that component?
Since components are the basic unit of code reuse in React, let's try refactoring the code a bit to use a `<Mouse>`component that encapsulates the behavior we need to reuse elsewhere.
{/* ...but how do we render something other than a <p>? */}
79
+
{/* ...但我们如何渲染 <p> 以外的东西? */}
80
80
<p>The current mouse position is ({this.state.x}, {this.state.y})</p>
81
81
</div>
82
82
);
@@ -87,19 +87,19 @@ class MouseTracker extends React.Component {
87
87
render() {
88
88
return (
89
89
<div>
90
-
<h1>Move the mouse around!</h1>
90
+
<h1>移动鼠标!</h1>
91
91
<Mouse />
92
92
</div>
93
93
);
94
94
}
95
95
}
96
96
```
97
97
98
-
Now the`<Mouse>`component encapsulates all behavior associated with listening for `mousemove`events and storing the (x, y) position of the cursor, but it's not yet truly reusable.
For example, let's say we have a `<Cat>` component that renders the image of a cat chasing the mouse around the screen. We might use a `<Cat mouse={{ x, y }}>` prop to tell the component the coordinates of the mouse so it knows where to position the image on the screen.
100
+
举个例子,假设我们有一个 <Cat> 组件,它可以呈现一张在屏幕上追逐鼠标的猫的图片。我们或许会使用 `<Cat mouse={{ x, y }}` prop 来告诉组件鼠标的坐标以让它知道图片应该在屏幕哪个位置。
101
101
102
-
As a first pass, you might try rendering the `<Cat>`*inside`<Mouse>`'s `render` method*, like this:
102
+
首先, 你或许会像这样,尝试在 `<Mouse>`内部的渲染方法渲染`<Cat>` 组件::
103
103
104
104
```js
105
105
classCatextendsReact.Component {
@@ -130,10 +130,9 @@ class MouseWithCat extends React.Component {
We could just swap out the <p> for a <Cat> here ... but then
134
-
we would need to create a separate <MouseWithSomethingElse>
135
-
component every time we need to use it, so <MouseWithCat>
136
-
isn't really reusable yet.
133
+
我们可以在这里换掉 <p> 的 <Cat> ......
134
+
但是接着我们需要创建一个单独的 <MouseWithSomethingElse>
135
+
每次我们需要使用它时,<MouseWithCat> 是不是真的可以重复使用.
137
136
*/}
138
137
<Cat mouse={this.state} />
139
138
</div>
@@ -145,17 +144,17 @@ class MouseTracker extends React.Component {
145
144
render() {
146
145
return (
147
146
<div>
148
-
<h1>Move the mouse around!</h1>
147
+
<h1>移动鼠标!</h1>
149
148
<MouseWithCat />
150
149
</div>
151
150
);
152
151
}
153
152
}
154
153
```
155
154
156
-
This approach will work for our specific use case, but we haven't achieved the objective of truly encapsulating the behavior in a reusable way. Now, every time we want the mouse position for a different use case, we have to create a new component (i.e. essentially another `<MouseWithCat>`) that renders something specifically for that use case.
Here's where the render prop comes in: Instead of hard-coding a `<Cat>`inside a `<Mouse>`component, and effectively changing its rendered output, we can provide `<Mouse>`with a function prop that it uses to dynamically determine what to render–a render prop.
@@ -199,7 +198,7 @@ class MouseTracker extends React.Component {
199
198
render() {
200
199
return (
201
200
<div>
202
-
<h1>Move the mouse around!</h1>
201
+
<h1>移动鼠标!</h1>
203
202
<Mouse render={mouse=> (
204
203
<Cat mouse={mouse} />
205
204
)}/>
@@ -209,17 +208,17 @@ class MouseTracker extends React.Component {
209
208
}
210
209
```
211
210
212
-
Now, instead of effectively cloning the `<Mouse>`component and hard-coding something else in its `render` method to solve for a specific use case, we provide a `render` prop that `<Mouse>`can use to dynamically determine what it renders.
More concretely, **a render prop is a function prop that a component uses to know what to render.**
213
+
更具体地说,**render prop 是一个用于告知组件需要渲染什么内容的函数 prop。**
215
214
216
-
This technique makes the behavior that we need to share extremely portable. To get that behavior, render a `<Mouse>`with a `render` prop that tells it what to render with the current (x, y) of the cursor.
One interesting thing to note about render props is that you can implement most [higher-order components](/docs/higher-order-components.html) (HOC) using a regular component with a render prop. For example, if you would prefer to have a `withMouse`HOC instead of a `<Mouse>`component, you could easily create one using a regular `<Mouse>`with a render prop:
It's important to remember that just because the pattern is called "render props" you don't *have to use a prop named`render`to use this pattern*. In fact, [*any* prop that is a function that a component uses to know what to render is technically a "render prop"](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce).
Although the examples above use `render`, we could just as easily use the `children` prop!
241
+
尽管之前的例子使用了 `render`,我们也可以简单地使用 `children` prop!
243
242
244
243
```js
245
244
<Mouse children={mouse=> (
246
-
<p>The mouse position is {mouse.x}, {mouse.y}</p>
245
+
<p>鼠标的位置是 {mouse.x},{mouse.y}</p>
247
246
)}/>
248
247
```
249
248
250
-
And remember, the `children` prop doesn't actually need to be named in the list of "attributes" in your JSX element. Instead, you can put it directly *inside* the element!
You'll see this technique used in the [react-motion](https://github.com/chenglou/react-motion) API.
259
+
你将在 [react-motion](https://github.com/chenglou/react-motion)的 API 中看到此技术。
261
260
262
-
Since this technique is a little unusual, you'll probably want to explicitly state that `children` should be a function in your `propTypes` when designing an API like this.
261
+
由于这一技术的特殊性,当你在设计一个类似的 API 时,你或许会要直接地在你的 propTypes 里声明 children 的类型应为一个函数。
263
262
264
263
```js
265
264
Mouse.propTypes= {
266
265
children:PropTypes.func.isRequired
267
266
};
268
267
```
269
268
270
-
## Caveats {#caveats}
269
+
## 注意事项 {#caveats}
271
270
272
-
### Be careful when using Render Props with React.PureComponent {#be-careful-when-using-render-props-with-reactpurecomponent}
Using a render prop can negate the advantage that comes from using [`React.PureComponent`](/docs/react-api.html#reactpurecomponent)if you create the function inside a `render` method. This is because the shallow prop comparison will always return `false` for new props, and each `render`in this case will generate a new value for the render prop.
For example, continuing with our `<Mouse>`component from above, if `Mouse`were to extend `React.PureComponent`instead of `React.Component`, our example would look like this:
@@ -287,8 +286,8 @@ class MouseTracker extends React.Component {
287
286
<h1>Move the mouse around!</h1>
288
287
289
288
{/*
290
-
This is bad! The value of the `render` prop will
291
-
be different on each render.
289
+
这是不好的!
290
+
每个渲染的 `render` prop的值将会是不同的。
292
291
*/}
293
292
<Mouse render={mouse=> (
294
293
<Cat mouse={mouse} />
@@ -299,14 +298,14 @@ class MouseTracker extends React.Component {
299
298
}
300
299
```
301
300
302
-
In this example, each time `<MouseTracker>`renders, it generates a new function as the value of the `<Mouse render>` prop, thus negating the effect of `<Mouse>`extending `React.PureComponent` in the first place!
To get around this problem, you can sometimes define the prop as an instance method, like so:
303
+
为了绕过这一问题,有时你可以定义一个 prop 作为实例方法,类似这样:
305
304
306
305
```js
307
306
classMouseTrackerextendsReact.Component {
308
-
//Defined as an instance method, `this.renderTheCat` always
309
-
//refers to *same* function when we use it in render
307
+
//定义为实例方法,`this.renderTheCat`始终
308
+
//当我们在渲染中使用它时,它指的是相同的函数
310
309
renderTheCat(mouse) {
311
310
return<Cat mouse={mouse} />;
312
311
}
@@ -322,4 +321,4 @@ class MouseTracker extends React.Component {
322
321
}
323
322
```
324
323
325
-
In cases where you cannot define the prop statically (e.g. because you need to close over the component's props and/or state)`<Mouse>`should extend `React.Component` instead.
0 commit comments