如何在 React / Preact(又名 <If> 组件)中传递条件子级
Posted
技术标签:
【中文标题】如何在 React / Preact(又名 <If> 组件)中传递条件子级【英文标题】:How to pass conditional children in React / Preact (aka. <If> component) 【发布时间】:2018-09-14 07:22:23 【问题描述】:有时我需要创建一个包装器元素,它会根据自己的逻辑显示其子项(或不显示),可以选择将它们包装在自己选择的元素中:
<SomeWrapper some=condition>
Hello
</SomeWrapper>
这是因为孩子(“你好”)是静态的。但是,如果要动态计算子节点并且可能只有在条件成立时才能明确定义,该怎么办?
<SomeWrapper some=condition>
<ul>
this.may.not.exist.unless.condition.map(item =>
<li key=item.id>item.text</li>
)
</ul>
</SomeWrapper>
这里,如果条件为假并且包装元素不使用其子元素,它们仍将被创建并向下传递,浪费资源并可能在过程中引发错误。
一种解决方案(可能是最好的?)是将内容包装在自己的组件中:
<SomeWrapper some=condition>
<InnerContent/>
</SomeWrapper>
这是有效的,因为(AFAIK,如果我错了,请纠正我)除非 SomeWrapper 真正决定使用其 children
属性,否则不会调用 InnerContent 的构造函数和渲染。
但是如果我不想为 3 行代码创建一个组件怎么办?
我在野外看到过两种选择,没有一种特别吸引人:
将 thunk 作为唯一的孩子传递:
<SomeWrapper some=condition>() =>
<ul>
this.may.not.exist.unless.condition.map(item =>
<li key=item.id>item.text</li>
)
</ul>
</SomeWrapper>
将 thunk 作为道具传递:
<SomeWrapper some=condition render=() =>
<ul>
this.may.not.exist.unless.condition.map(item =>
<li key=item.id>item.text</li>
)
</ul>
/>
我不喜欢它们,因为 lambda 会在代码中添加视觉噪音,更不用说浪费资源,在每次执行 render()
时重新创建 (AFAIK。)
还有其他我没有看到的解决方案吗?我应该总是使用 InnerContent 元素吗?
【问题讨论】:
做 <condition here> && ...map(item => <li>..</li> )
而不是添加Wrapper有什么问题吗?
我不会担心浪费资源。甚至反应新的上下文 API 使用渲染道具。
哦,有趣!我很好奇 <condition here> && ...map(item => <li>..</li> )
是怎么浪费资源的?有条件不是不做图吗?
@KennethTruong condition && ...
不会浪费任何资源,但它会在 SomeWrapper 道具和 curly 表达式中重复条件表达式,我宁愿避免重复。
@TomaszMularczyk 你是说这个吗? <SomeCtx.Consumer>ctx => ...</SomeCtx.Consumer>
这看起来很像我的示例 #1。你会说它比示例 #2 更惯用吗?
【参考方案1】:
您可以简单地执行以下操作
<Container>
yourCondition === true && <ConditionalChildElement/>
</Container>
【讨论】:
【参考方案2】:看起来 render props 是一个东西,其实有一个 React 页面解释了它们的用法和最佳实践:
https://reactjs.org/docs/render-props.html
【讨论】:
以上是关于如何在 React / Preact(又名 <If> 组件)中传递条件子级的主要内容,如果未能解决你的问题,请参考以下文章
在 Preact 和 typescript 中使用 web 组件
如何使用 Preact 和 TypeScript 对子组件进行类型检查?