render prop 是一种通过函数类型的 prop 在 React 组件间共享逻辑的技术。具有 render prop 的组件接收一个返回值为 React 组件的函数,并在自身内部调用此函数来实现渲染逻辑。
基本范式
import React from "react";
class Mouse extends React.Component {
constructor(props) {
super(props);
this.state = {
x: 0,
y: 0,
};
this.handleMouseMove = this.handleMouseMove.bind(this);
}
handleMouseMove(e) {
this.setState({
x: e.clientX,
y: e.clientY,
});
}
render() {
return (
<div style={{ height: "100vh" }} onMouseMove={this.handleMouseMove}>
{this.props.children(this.state)}
</div>
);
}
}
class Box extends React.Component {
constructor(props) {
super(props);
}
render() {
const mouse = this.props.mouse;
return (
<div
style={{
width: "10px",
height: "10px",
backgroundColor: "red",
position: "absolute",
left: mouse.x,
top: mouse.y,
}}
/>
);
}
}
export class MouseTracker extends React.Component {
render() {
return (
<div>
<p>请移动鼠标!</p>
<Mouse>{(props) => <Box mouse={props} />}</Mouse>
</div>
);
}
}
render prop 是一个告知组件需要渲染什么内容的函数 prop。使用 render prop 时需要约定函数入参。
使用 render prop 可以实现大多数高阶组件(HOC)。
function withMouse(WrappedComponent) {
return class extends React.Component {
render() {
return (
<Mouse>
{(mouse) => <WrappedComponent {...this.props} mouse={mouse} />}
</Mouse>
);
}
};
}
render prop 由自身模式而得名,而属性名不必是 render。
注意事项
1. 和 React.PureComponent 一起使用
如果在 render 方法里面创建函数来使用 render prop,由于每次都生成新的函数,支持 render prop 的 React.PureComponent 组件将无法优化性能。
把传给 render prop 的函数保存为实例方法可以解决这一问题;如果该函数无法保存,则支持 render prop 的组件应继承自 React.Component。
class Mouse extends React.PureComponent {
// ...
}
class MouseTracker extends React.Component {
renderBox(mouse) {
return <Box mouse={mouse} />;
}
render() {
return (
<div>
<p>请移动鼠标!</p>
<Mouse>{this.renderBox}</Mouse>
</div>
);
}
}