介绍和使用render props
什么是render prop
官方解释:render prop是一种在React组件之间使用一个值为函数的prop共享代码的技术
即使用了render这个prop的组件,接受一个函数来渲染元素,即父组件控制这部分的显示内容,而不是组件内部去实现自己的渲染逻辑。而父组件渲染的元素使用的数据是子组件内部控制的状态。
比如下面这个例子:
1 | <SearchList render={ data => ({ |
data即为SearchList组件内部的state。
为什么要使用render prop
试想下面这种场景:
实现一个组件,用户边输入,边搜索,搜索结果展示为一个列表
实现思路:
- 首先需要一个输入框和一个结果列表
- 使用debounce,间隔一段时间请求一次,渲染结果上面实现了基本的功能,请求防抖和列表展示;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
export default class SearchList extends React.Component {
constructor(props) {
super(props);
this.lastFetchId = 0;
this.handleSearch = debounce(this.handleSearchB, 600);
this.state = {
value: '',
optionList: [], // 可选列表
};
}
onChange = (e) => {
const value = e && e.target && e.target.value;
this.handleSearch(value);
}
handleSearch = async (val) => {
if (val) {
this.lastFetchId += 1;
const fetchId = this.lastFetchId;
if (fetchId !== this.lastFetchId) {
return;
}
// 此处请求并处理结果
}
}
render() {
const { value, optionList } = this.state;
return (
<div className='content'>
<input type="text" value={value} onChange={this.onChange} placeholder="请输入"/>
<ul className="search-list">
{
optionList.map(item => (
<li className="item" key={item.id}>{item.name}</li>
}
</ul>
</div>
);
}
}
下面改动一下需求:如果一个页面需要显示的是商品列表,另一个页面显示的品牌列表,展示的形式是一样的,但是因为接口的不同,需要展示的内容可能不一样。比如品牌列表需要展示品牌名,品牌知名度,商品列表需要展示商品名称,商品属性等信息;对于品牌,如果返回结果为空,则展示用户输入的品牌,并添加此品牌保证他始终能搜到结果。
你可能会想到把列表放到父组件去维护,渲染的时候采用children的方式,这是一种方法,因为父组件本身也需要使用列表数据,但是列表的处理逻辑更多的在子组件中,个人觉得这种处理方式并没有达到组件封装的目的。
这样就可以用到render prop来解决了
商品列表:
1 | <SearchList render={ data => ({ |
品牌列表:
1 | <SearchList render={ (data, value) => ({ |
修改一下SearchList组件
1 | render () { |
总结
总结:render prop是一个用于告知组件需要渲染什么内容的函数prop,而具体的使用场景就是一个组件渲染的部分,需要父组件决定,虽然大多数场景我们可以通过使用children prop的方式来实现,但当父组件需要渲染的部分的数据依赖子组件内部状态时,就需要使用render prop了,更直白的说,就是这个组件的基础功能是提供可变数据源的时候,具体展示可以从外部注入。
可变数据源组件:自己不知道要渲染什么,只是一个基础数据提供者