假设一个组件需要渲染一堆元素,但渲染必须是可定制的,因为这个组件会在很多地方重复使用。可以把它想象成一个需要渲染事件的日历组件,但事件渲染逻辑应该可以通过日历组件的 props 来控制。
到目前为止,我发现了两种方法可以做到这一点,我不确定哪种方法是正确的,哪种方法是错误的,如果一种方法与另一种方法相比有缺点
1-传递执行渲染的回调
type MainProps = {
renderStuff: (stuff) => void;
};
function MainComponent(props: MainProps){
const matchingStuff = [1, 2, 3...]
return (
<ul>
{matchingStuff.map(stuff => <li>{renderStuff(stuff)}</li>)}
</ul>
);
}
2- 将组件定义作为 prop 传递:
type StuffProps = {
stuff: number;
}
type MainProps = {
renderStuff: FC<StuffProps>;
};
function MainComponent(props: MainProps){
const matchingStuff = [1, 2, 3...]
return (
<ul>
{matchingStuff.map(stuff => <props.renderStuff stuff={stuff} />)}
</ul>
);
}
function Stuff(props: StuffProps){
return <li>{props.stuff}</li>
}
(注意
renderStuff
的类型差异)
我不知道什么是正确的和错误的方式
不,没有正确或错误的方式,两者都有效(尽管不是以相同的方式 - 见下文),并且是各种高质量反应库中存在的模式。
一些React库实际上同时使用了两者:https://v5.reactrouter.com/web/api/Route
这只是呈现 API 的一种方式。
在某些情况下,您会发现无法使用其中一种,或者其中一种比另一种性能更高。但当你看到这些情况时,你通常就会知道它们。
如果您传递内联函数并将其呈现为组件,则会出现最大的问题,如下所示:
const MyParent = () => <MyChild Component={({prop}) => <>Some Stuff - {prop}</>}/>
const MyChild = ({Component}) => <Component prop={"Render me!"}/>
在我发布的上面的示例中,这是无关紧要的,因为内联函数中没有状态。如果有状态,您会看到每次渲染
MyParent
时,状态都会在 MyChild
中重置,因为它每次都是一个新组件(内联函数)。
在上面的示例中,您可以在渲染函数外部声明组件并将其作为 prop 传递,如下所示:
const MyParentRenderComponent = ({prop}) => <>Some Stuff - {prop}</>
const MyParent = () => <MyChild Component={MyParentRenderComponent}/>
这是 React 中的标准规则:不要在渲染函数(或功能组件的主体)内声明组件,因此它并不是这种情况所独有的。