我有一个子组件,根据它的一些道具最终会呈现某些东西。孩子们的渲染功能看起来像这样:
render() {
if (props.a == 'foo' && props.b == 'bar') {
return (<p> Hey There </p>);
} else if {props.a == 'z') {
return (<p> Hey There </p>);
} // more conditions
} else {
return null
}
}
在父组件中,我渲染了几个子组件,我需要知道它们中有多少会呈现,因为根据这个数字我会做什么或不做。我不想重复从孩子到父母的条件逻辑,但我不知道如何从父母那里知道孩子是否会被渲染。
答案 0 :(得分:4)
你想要做的是在React中有点反模式。 如果我理解你的问题,子渲染输出会影响他们的父渲染输出,这可能会让你陷入渲染循环。
我建议你让孩子们的组件尽可能简单,并将条件逻辑提升到父母,这样你就可以计算你将要渲染的孩子数量。
如果我的问题出错了,请告诉我。
答案 1 :(得分:1)
虽然我同意perpetualjourney的回答,但我认为我可以给你一个计算孩子的可能性。
最简单的方法是先将子项的渲染保存到变量中,然后再渲染该结果。
var kids = this.props.items.map( (k, i) => <Kid condition={k} key={i} /> );
var totalKids = kids.reduce( (k, i) => k + (i.type( i.props ) ? 1 : 0), 0);
现在,这会让你的孩子两次,所以当你已经有一个性能沉重的方法时,这不是最好的
const Kid = ({ condition }) => condition % 3 === 0 ? <h1>{ condition }</h1> : null;
class ConditionalKids extends React.Component {
render() {
var kids = this.props.items.map( (k, i) => <Kid condition={k} key={i} /> );
var totalKids = kids.reduce( (k, i) => k + (i.type( i.props ) ? 1 : 0), 0);
return <div>
<p>Rendered in total { totalKids }</p>
{ kids }
</div>;
}
}
const items = [...new Array(5)].map( i => parseInt( Math.random() * 10 ) );
console.log( items );
const target = document.querySelector('#container');
ReactDOM.render( <ConditionalKids items={items} />, target );
&#13;
<script id="react" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.js"></script>
<script id="react-dom" src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.js"></script>
<div id="container"></div>
&#13;
答案 2 :(得分:0)
处理此问题的一种方法是使用3.14 == 3.1400
。
在此CodeSandbox example中,我使用state
逻辑更新组件的if/else
。这是在state
生命周期方法中完成的。
您的componentWillReceiveProps
方法已简化为render
语句。
如果您想根据switch
逻辑调用命令式API,可以在if/else
生命周期方法中执行此操作。这也简化为componentDidUpdate
语句。
答案 3 :(得分:0)
这是一个非常相关的问题,会影响任何复杂性的应用程序。不幸的是,目前还没有明确的方法使用React对此建模。我已经做了很多React,并会推荐@perpetualjourney所说的话:将逻辑提升给一个共同的父母。有时,您需要将其向上移动,但不要像React.Children.map
或React.Context
那样弄乱它们,因为它们会在组件之间建立依赖关系,并且使您难以移动它们如果需要的话。
const hasA = computeHasA({ ... });
const hasB = computeHasB({ ... });
const hasAny = hasA || hasB;
if (hasAny) {
return (
<Tabs>
{hasA && <Tab title="A">Some content</Tab>}
{hasB && <Tab title="B">Another content</Tab>}
</Tabs>
);
}
例如,当您真的无法向上移动逻辑时,如果孩子们提出网络请求(这可能是一个极端的情况),我建议您传递一个用于报告他们是否有内容并存储的道具。进入父母的状态:
const [numberOfRenderedChildren, setNumberOfRenderedChildren] = useState(0);
const incrementNumberOfRenderedChildren = () => {
// Use a callback to prevent race conditions
setNumberOfRenderedChildren(prevValue => prevValue + 1);
};
return (
<MyContainer isVisible={numberOfRenderedChildren > 0}>
{items.map(item => (
<ComplexChild
key={item.id}
// Avoid spreading props like ...item. It breaks semantics
item={item}
reportHasContent={incrementNumberOfRenderedChildren}
/>
)}
</MyContainer>
);
如果您需要加载程序和错误消息,它可能会变得更加复杂,但是我会触发父级中的所有请求。即使它意味着更多的冗长性,也请尝试使其简单,易于阅读。几周后需要返回这些文件时,您将不会后悔。