render属性可以实现组件之间共享代码,值是一个函数,返回一个有自身渲染逻辑的组件,结构一般如下

<DataProvider render={(data) => <h1>Hello {data.target}</h1>} />

举个栗子

比如我们有一个 Cat 组件,监听鼠标 xy 并展示

class Cat extends React.Component {
render() {
const { mouse } = this.props;
return (
<div>
{mouse.x}-{mouse.y}
</div>
);
}
}

MouseWithCat 组件监听鼠标的变化并将状态传递给 Cat

class MouseWithCat extends React.Component {
state = {
x: 0,
y: 0,
};
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
render() {
return (
<div
style={{ width: 400, height: 400, border: '1px solid #e5e5e5' }}
onMouseMove={this.handleMouseMove}
>
<Cat mouse={this.state} />
</div>
);
}
}

这样看起来没什么问题,但是如果来了一个新的 Dog 组件,也需要实现同样的功能,那么就需要再写一遍

class MouseWithDog extends React.Component {
state = {
x: 0,
y: 0,
};
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
render() {
return (
<div
style={{ width: 400, height: 400, border: '1px solid #e5e5e5' }}
onMouseMove={this.handleMouseMove}
>
<Dog mouse={this.state} />
</div>
);
}
}

以此类推,如果所需要的场景增多了,就会产生大量重复代码,于是 render 属性派上用场了,我们可以通过传递一个函数来决定渲染什么子组件,我们先把 Mouse 组件改变一下,通过调用父级传递的render方法来传递自身的 state

class Mouse extends React.Component {
state = {
x: 0,
y: 0,
};
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
render() {
return (
<div
style={{ width: 400, height: 400, border: '1px solid #e5e5e5' }}
onMouseMove={this.handleMouseMove}
>
{/* 调用props传递的render方法 */}
{this.props.render(this.state)}
</div>
);
}
}
class MouseTrack extends React.Component {
render() {
return <Mouse render={(mouse) => <Cat mouse={mouse} />} />;
}
}

这时候如果新增一个 Dog,Pig 都没问题,直接调用就行了

class MouseTrack extends React.Component {
render() {
{
/* return (<Mouse render={ mouse => (<Pog mouse={ mouse } />) }/>) */
}
return <Mouse render={(mouse) => <Dog mouse={mouse} />} />;
}
}

总结

render属性的值是一个函数,通过函数可以传参来动态实现需要渲染的组件

当然我们还可以用高阶组件来实现组件功能的复用,高阶组件的定义是通过包裹(wrapped)被传入的 React 组件,经过一系列处理,最终返回一个相对增强(enhanced)的 React 组件,供其他组件调用

声明一个 WithMouse 的高阶组件

import Mouse from './Mouse';
import React from 'react';
export default function WithMouse(Component) {
return class extends React.Component {
render() {
return (
<Mouse
render={(mouse) => <Component {...this.props} mouse={mouse} />}
/>
);
}
};
}

在定义 Cat 组件的时候通过 WithMouse 高阶函数来增加 Cat 的功能

import React from 'react'
import WithMouse from './WithMouse'
class Cat extends React.Component {
render() {
const { mouse } = this.props
return (
<div>{ mouse.x }-{ mouse.y }</div>
)
}
}
export default WithMouse(Cat)