What is the proper way to handle conditional rendering?
Let's say I have a very simplified version like this, which seems to be a pretty normal react-approach if i'm not mistaken? If I console.log inside of Child we will see it enters it everytime the state of Parent changes - even if show is set to false, and we don't want it to render.
Doesn't that take some performance even if it is not rendering anything? Let's say we have a very advanced page with loads of conditional renders - all of the components will get entered fast and then exited without rendering.
const Parent = () => {
const [show, setShow] = useState(false)
return (
<Button onClick={() => setShow={true}}
<Child show={show} setShow={setShow} />
)
}
Another way of handling it is like this (which I have not seen, so I guess for some reason it is not better) here we will only enter the Child if show is actually true.
const Parent = () => {
const [show, setShow] = useState(false)
return (
<Button onClick={() => setShow={true}}
{show && <Child setShow={setShow} />}
)
}
CodePudding user response:
These are two common approaches, but they have different implications: in the first approach, <Child>
actually mounts, which you might want in the case that it is doing some work or maintaining some state that should persist whether or not the component is shown. Imagine, for example, that you have a component which makes a network call to get initial state when it mounts - you wouldn't want to continually unmount and remount that component, since that would result in a new network call on each remount. Instead, you can keep the state tracked in the component and simply conditionally avoid putting any UI into the DOM when you don't need it.
In the second approach, the component is unmounted unless show
is true; the effect of this is that its state and event handlers will be reset each time the component is hidden and then shown.
See this sandbox for a demonstration of the difference.
As you've noted, rendering a hidden component does have performance implications, but it should generally be done when you need React to be tracking that component in the tree regardless of visibility, so it's a price that's likely worth paying in that scenario. When you don't actually need a hidden component in the tree, it may be simpler to simply short circuit so that you don't render it.
CodePudding user response:
The performance difference is likely to be minimal, I would not worry about it until you can measure some issues. Your observation with the console.log
's are correct, if there is expensive code run every Child
render than it would be best to not render it at all. Even if you return <></>
from Child
, the code before that return all still runs.
In the general case, The parent should handle if the child renders (your second code snippet). The reason being that you can reduce the amount of logic in the child component as it can happily assume it always renders whenever called. You could then reuse the child component in places where it does not conditionally render without having an extra show={true}
at its use-site.
There are some exceptions, some components should handle their own rendering, a Model comes to mind. I think this mostly comes down to Models and similar components not being visually contained within their parent component. They also often have to maintain state between being shown and hidden that you do not want to lift up to its parent.