一种在 React 组件之间使用一个值为函数的prop, 在React 组件间共享代码的简单技术
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 (
Move the mouse around!
The current mouse position is ({this.state.x}, {this.state.y})
);
}
}
随着鼠标在屏幕上移动,在一个 p 标签的组件上显示它的 (x, y) 坐标。
假设我们现在有一个在屏幕上跟随鼠标渲染一张猫的图片的
组件。我们可能使用
首先,你可能会像这样,尝试在 的内部的渲染方法渲染 组件:
class Cat extends React.Component {
render() {
const mouse = this.props.mouse
return (
);
}
}
class MouseWithCat 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 (
);
}
}
这一方法对我们的具体用例来说能够生效,但我们却没法实现真正的将行为封装成可重用的方式的目标。现在,每次我们在不同的用例中想要使用鼠标的位置,我们就不得不创建一个新的针对那一用例渲染不同内容的组件 (如另一个关键的
)。
class Cat extends React.Component {
render() {
const mouse = this.props.mouse
return (
);
}
}
function withMouse(Component) {
return class 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 (
)
}
}
}
export default withMouse(Cat);
我们可以提供一个带有函数 prop 的
组件,它能够动态决定什么需要渲染的,而不是将 硬编码到
组件里,并有效地改变它的渲染结果。
class Cat extends React.Component {
render() {
const mouse = this.props.mouse;
return (
);
}
}
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 (
{/*
Instead of providing a static representation of what renders,
use the `render` prop to dynamically determine what to render.
*/}
{this.props.render(this.state)}
);
}
}
class MouseTracker extends React.Component {
render() {
return (
Move the mouse around!
(
)}/>
);
}
}
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 (
{this.props.render(this.state)}
);
}
}
function withMouse(Component) {
return class extends React.Component {
render() {
return (
(
)}/>
);
}
}
}
class Mouse extends React.PureComponent {
}
class MouseTracker extends React.Component {
render() {
return (
Move the mouse around!
(
)}/>
);
}
}
在这样例子中,每次
渲染,它会生成一个新的函数作为
的 prop,因而在同时也抵消了继承自 React.PureComponent 的
组件的效果!
为了绕过这一问题,有时你可以定义一个 prop 作为实例方法,类似如下:
class MouseTracker extends React.Component {
constructor(props) {
super(props);
this.renderTheCat = this.renderTheCat.bind(this);
}
renderTheCat(mouse) {
return ;
}
render() {
return (
Move the mouse around!
);
}
}
参考链接https://react.docschina.org/docs/render-props.html#%E5%9C%A8%E4%BA%A4%E5%8F%89%E5%85%B3%E6%B3%A8%E7%82%B9%EF%BC%88cross-cutting-concerns%EF%BC%89%E4%BD%BF%E7%94%A8-render-props