render props 是一个非常流行的用于组件之间逻辑复用的开发模式,自从 React 16.8 出现了 自定义 Hook,并用于组件之间的逻辑复用后,render props 是不是就不再被需要了呢? 答案是 NO! render props 对于构建可重用的组件仍然有用
什么是 render prop
一个 render prop 是一个函数类型的组件属性(prop),该函数的返回值用于渲染一些东西,比如渲染一个 JSX
interface Props {
...
renderItem?: (item: string) => JSX.Element;
renderHeader?: () => JSX.Element;
}
复制代码
这样做可以让组件的使用者来决定某一个具体的位置需要渲染什么。 这就使组件非常灵活且高度可重用。
每一个组件都有一个 render prop
每一个组件都有一个 children属性
export const Card: FC = ({ children }) => (
<div className="card">{children}</div>
);
复制代码
children 就是一个 render prop, 在上面的示例中,children 属性允许组件的使用者渲染自定义的内容。如:
<Card>
<p>Some interesting text</p>
<button>Click me</button>
</Card>
复制代码
创建 render prop
让我们创建自己的 render prop
interface Props {
title?: string;
renderHeader?: () => JSX.Element;
}
export const Card: FC<Props> = ({ children, title, renderHeader }) => (
<div className="card">
<div className="card-header">
{renderHeader ? renderHeader() : title !== undefined ? title : null}
</div>
<div className="card-content">{children}</div>
</div>
);
复制代码
我们的Card
组件组件有一个头部(header),使用者可以使用 renderHeader
覆盖头部的默认展示效果
下面看看如何使用Card
组件
<Card renderHeader={() => <h3>A custom header</h3>}>
<p>Some interesting text</p>
<button>Click me</button>
</Card>
复制代码
上面是一个 在Card
组件中使用renderHeader
属性自定义渲染头部效果的例子,renderHeader
属性是一个箭头函数,并返回一个h3
标签包裹的内容
现在,我们开始了解 render props 的作用以及让它如何在组件中具有超级的灵活性和可重用性。
创建一个可以重用的列表组件
interface Props {
data: string[];
renderItem?: (item: string) => JSX.Element;
renderHeader?: () => JSX.Element;
}
export const List: FC<Props> = ({ data, renderItem, renderHeader }) => (
<div className="list">
<div className="list-header">{renderHeader && renderHeader()}</div>
<ul>
{data.map((item) => (
<li key={item}>{renderItem ? renderItem(item) : item}</li>
))}
</ul>
</div>
);
复制代码
上面是一个简单的List
组件,此组件有两个 render prop-renderItem
和renderHeader
。注意renderItem
有一个参数,此参数被用来显示界面上
<List
data={["Fred", "Bob", "Jane"]}
renderHeader={() => <h3>Names</h3>}
renderItem={(item) => (
<div>
<span style={{ marginRight: "10px" }}>{item}</span>
<button>Click me</button>
</div>
)}
/>
复制代码
上面试使用List
组件的一个例子,
- 使用
renderHeader
属性作为一个箭头函数并h3
包裹的内容 - 使用
renderItem
属性返回列表的每一项并且与一个 按钮组件在一起,作为每一行数据的渲染结果
总结
-
当组件使用者需要在高度可重用的组件中渲染自定义组元素时, render props 仍然是非常有用的
-
每个 React 组件都会有一个 render prop-
children
,以允许使用者在组件的某个位置渲染自定义元素。 -
我们可以在组件中创建我们自己的 render props,以允许使用者在组件的多个不同位置渲染自定义元素。
-
render props 可以接受一些参数,这些参数在使用 render prop 来渲染数据项列表时非常有用。
参考文档:Render props are still useful | Building SPAs