Published

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?.

More like this