"Render Props"是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术。
具有 render prop 的组件接受一个函数,该函数返回一个 React 元素并调用它而不是实现自己的渲染逻辑。
<DataProvider render={data => (
<h1>Hello {data.target}</h1>
)}/>
是不是很简单,更具体地说,render prop 是一个用于告知组件需要渲染什么内容的函数 prop。
照例,卷起袖子撸代码~~~
class Mouse 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}>
{/* ...但我们如何渲染 <p> 以外的东西? */}
<p>
The current mouse position is ({this.state.x}, {this.state.y})
</p>
{this.props.render(this.state)}
</div>
);
}
}
class MouseTracker extends React.Component {
render() {
return (
<div style={{ height: "100vh", backgroundColor: "#676767" }}>
<h1>移动鼠标!</h1>
<Mouse
render={mouse => {
if (mouse.x > 500 && mouse.y > 500) {
return <Dog mouse={mouse} />;
} else {
return <Cat mouse={mouse} />;
}
}}
/>
</div>
);
}
}
class App extends React.Component {
render() {
return (
<div>
<MouseTracker />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
实例中,我们在
<Mouse>
中监听光标在屏幕上移动,获取其位置。然后将<Cat>
组件(还有<Dog>
组件)也显示到光标的位置。
以往做法,
可以尝试在<Mouse>
内部的直接渲染<Cat>
组件,采用组合组件的方式实现;
也可以采用HOC(高阶组件)的方式实现。但是这些方式都得创建组件。
如果采用render prop 可以轻松解决。
我们提供了一个 render 方法 让 <Mouse> 能够动态决定什么需要渲染,而不是克隆 <Mouse> 组件然后硬编码来解决特定的用例。这种实现方式比尝试在 <Mouse> 内部的渲染方法渲染 <Cat> 组件要方便的多,不用每次都得创建新的组件。
惊喜
关于 render prop 一个有趣的事情是你可以使用带有 render prop 的常规组件来实现大多数高阶组件 (HOC)。 例如,如果你更喜欢使用 HOC而不是组合组件,你可以使用带有 render prop 的常规 <Mouse>
轻松创建一个:
// 如果你出于某种原因真的想要 HOC,那么你可以轻松实现
// 使用具有 render prop 的普通组件创建一个!
function withMouse(Component) {
return class extends React.Component {
render() {
return (
<Mouse render={mouse => (
<Component {...this.props} mouse={mouse} />
)}/>
);
}
}
}
注意点
使用 Props 而非 render
重要的是要记住,render prop 是因为模式才被称为 render prop ,你不一定要用名为 render
的 prop 来使用这种模式。事实上, 任何被用于告知组件需要渲染什么内容的函数 prop 在技术上都可以被称为 “render prop”.
尽管之前的例子使用了 render,我们也可以简单地使用 children prop!
<Mouse children={mouse => (
<p>鼠标的位置是 {mouse.x},{mouse.y}</p>
)}/>
其他的注意事项可以去官网看看细节,这边就不累赘了(这里的基本够用,但是细节不足,翻阅官网资料就当多看一遍加深印象吧!)
Render Props直通车