admin管理员组文章数量:1289525
I have a child ponent that depending on some of its props will end up rendering something or not. The render function of the children looks something like this:
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
}
}
In the parent ponent I am rendering several child ponents, and I need to know how many of them will render, because depending on that number I will do something or not. I don't want to repeat the conditional logic from the child to the parent, but I don't know how from a parent I can find out if the children will render or not.
I have a child ponent that depending on some of its props will end up rendering something or not. The render function of the children looks something like this:
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
}
}
In the parent ponent I am rendering several child ponents, and I need to know how many of them will render, because depending on that number I will do something or not. I don't want to repeat the conditional logic from the child to the parent, but I don't know how from a parent I can find out if the children will render or not.
Share Improve this question edited Feb 16, 2018 at 10:42 Hommer Smith asked Feb 15, 2018 at 13:57 Hommer SmithHommer Smith 27.9k62 gold badges176 silver badges307 bronze badges 2- If a parent renders, all children will render unless some of them have implemented shouldponentUpdate which returns false or if they the PureComponent in which case a shallow parison is done between state and props for them – Shubham Khatri Commented Feb 15, 2018 at 14:05
-
The render function looks something like this
, render function of what , child or parent. – Shubham Khatri Commented Feb 15, 2018 at 14:09
4 Answers
Reset to default 4What you're trying to do is a bit of an anti-pattern in React. If I understand your question, the children render output would influence their parent's render ouptput, which is likely to get you stuck in a render loop.
I suggest you keep the children ponents as simple as possible and hoist the conditional logic to the parent which will allow you to count how many children you'll be rendering in place.
Please let me know if I got your question wrong.
Although I agree with perpetualjourney's answer, I thought I could give you a possibility of counting the children.
The easiest would be to save the rendering of the children first to a variable and then to render that result.
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);
Now, this will render your children twice, so it is not the best when you already have a performance heavy method
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 );
<script id="react" src="https://cdnjs.cloudflare./ajax/libs/react/15.6.2/react.js"></script>
<script id="react-dom" src="https://cdnjs.cloudflare./ajax/libs/react-dom/15.6.2/react-dom.js"></script>
<div id="container"></div>
One way of handling this problem is to use state
.
In this CodeSandbox example, I use the if/else
logic to update the ponent's state
. This is done inside the ponentWillReceiveProps
lifecycle method.
Your render
method is simplified to a switch
statement.
If you want to call an imperative API based on the if/else
logic you have, you can do that inside your ponentDidUpdate
lifecycle method. This is also simplified to a switch
statement.
That's a very pertinent question that affects applications of any plexity. Unfortunately there's no clear way to model this using React today. I've done a ton of React and would remend what @perpetualjourney said: hoist the logic to a mon parent. Sometimes you'll need to move it way up, but do it instead of messing around with React.Children.map
or React.Context
since they'd create dependency between the ponents and would make it harder for you to move them around if needed.
const hasA = puteHasA({ ... });
const hasB = puteHasB({ ... });
const hasAny = hasA || hasB;
if (hasAny) {
return (
<Tabs>
{hasA && <Tab title="A">Some content</Tab>}
{hasB && <Tab title="B">Another content</Tab>}
</Tabs>
);
}
When you really can't move to logic upwards, for example, if the children do network requests, which is probably an edge-case, I'd remend passing a prop used to report whether they have content or not and storing it into the parent's state:
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>
);
It could get more plex if you need loaders and error messages, but then I'd fire all the requests in the parent. Try to keep it simple, easy to read, even if it means more verbosity. You won't regret when you need to e back to those files a few weeks later.
本文标签: javascriptReact parent component check if child will renderStack Overflow
版权声明:本文标题:javascript - React parent component check if child will render - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741418744a2377678.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论