React basics: Can I use a switch statement to render components in React?
You can safely use any plain old JavaScript to dynamically render components in React, so long as you do not make and use a component dynamically. The following all behave exactly the same in React:
✅ Ternary:
const LightSwitch = () => { const [enabled, setEnabled] = useState(false)
return ( <div> {enabled ? <LightSwitchOn /> : <LightSwitchOff />} </div> )}
✅ Render function:
const LightSwitch = () => { const [enabled, setEnabled] = useState(false)
const renderComponent = () => { if (enabled) { return <LightSwitchOn /> }
return <LightSwitchOff /> } return ( <div> {renderComponent()} </div> )}
✅ Switch in a render function:
const LightSwitch = () => { const [enabled, setEnabled] = useState(false)
const renderCompoent = () => { switch (enabled) { case true: return <LightSwitchOn /> case false: return <LightSwitchOff /> } }
return ( <div> {renderComponent()} </div> )}
When using a switch statement like this, make sure that the cases in your switch-statement handle all possible values. If you forget to handle a value (e.g. null
or undefined
during loading), your component will unmount and remount, making the switch behave differently from the other examples.
✅ You can also inline it with a self-invoking anonymous function:
const LightSwitch = () => { const [enabled, setEnabled] = useState(false)
return ( <div> {(() => { switch (enabled) { case true: return <LightSwitchOn /> case false: return <LightSwitchOff /> } })()} </div> )}
But this can get messy quickly when your component gets larger.
I almost exclusively use the ternary pattern, as it is by far the simplest. Keeping my code as simple as possible is very important to me.
❌ The main thing to avoid is dynamically creating components as shown in the next code snippet.
const LightSwitch = () => { const [enabled, setEnabled] = useState(false)
const Component = () => { if (enabled) { return <LightSwitchOn /> }
return <LightSwitchOff /> }
return ( <div> <Component /> </div> )}
What happens here is that we're making a component-like function and calling it like you would any other component. React won't be able to recognize that the component is the same across renders, leading to the entire child-tree being remounted.
If you replaced <Component />
with {Component()}
, this would behave exactly the same as the render function example above. The only problem is that it's much harder to see what is going on, so I recommend using the renderX
naming scheme instead.
✅ The following snippet may appear like it also runs into this issue of dynamically making a component. But since it doesn't actually create a new function, the correct component references are used and it works as you would expect.
const LightSwitch = () => { const [enabled, setEnabled] = useState(false)
const Component = enabled ? LightSwitchOn : LightSwitchOff
return ( <div> <Component /> </div> )}
There are some niche use-cases for this last pattern, but in general I recommend avoiding it as it can be hard to follow. While this may seem like a smart way of conditionally rendering a component, often the simplest solution (the ternary) is the best.
This gist was inspired by the following question on Stack Overflow: The components are getting unmounted and mounted again if we use switch case, Why?.