render prop
是一个技术概念。它指的是使用值为function类型的prop来实现React component之间的代码共享。
如果一个组件有一个render属性,并且这个render属性的值为一个返回React element的函数,并且在组件内部的渲染逻辑是通过调用这个函数来完成的。那么,我们就说这个组件使用了render props
技术。
<DataProvider render={data => (
<h1>Hello {data.target}</h1>
)}/>
不少类库都使用了这种技术,比如说:React Router和Downshift。
在这个文档里面,我们将会讨论为什么render props
是如此有用,你该如何编写自己的render props
组件。
正文
使用Render Props来完成关注点分离
在React中,组件是代码复用的基本单元(又来了,官方文档不断地在强调这个准则)。到目前为止,在React社区里面,关于共享state或者某些相似的行为(比如说,将一个组件封装进另一拥有相同state的组件)还没有一个明朗的方案。
举个例子,下面这个组件是用于在web应用中追踪鼠标的位置:
class MouseTracker extends React.Component {
constructor(props) {
super(props);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.state = {
x: 0, y: 0 };
}
handleMouseMove(event) {
this.setState({
x: event.clientX,
y: event.clientY
});
}
render() {
return (
<div style={
{
height: '100%' }} onMouseMove={
this.handleMouseMove}>
<h1>Move the mouse around!</h1>
<p>The current mouse position is ({
this.state.x}, {
this.state.y})</p>
</div>
);
}
}
随着光标在屏幕上面移动,这个组件将会在文档的<p>
标签里面显示当前光标在x,y轴上的坐标值。
那么问题来了: 我们该如何在别的组件复用这种行为(指的是监听mouseMove事件,获取光标的坐标值)呢?换句话说,如果别的组件也需要知道目前光标的坐标值,那我们能不能将这种行为封装好,然后在另外一个组件里面开箱即用呢?
因为,在React中,组件是代码复用的基本单元(again)。那好,我们一起来重构一下代码,把我们需要复用的行为封装到<Mouse>
组件当中。
// The <Mouse> component encapsulates the behavior we need...
class Mouse extends React.Component {
constructor(props) {
super(props);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.state = {
x: 0, y: 0 };
}
handle