DEV Community

Vays
Vays

Posted on

No more conditional renderings abuse

This morning, while browsing through my old GitHub repositories, I came across a component from my first ReactJS project and I noticed a small mistake. I'll let you guess what it is before giving you the answer.

Here's the component:

function FoodAlert() {
const {data, isLoading} = useData();

return <Alert>
    <AlertTitle>Too much</AlertTitle>
    <AlertDescription>
        <h2>It seems to be enough</h2>
        <div>
            {data ? <h3>you put on {data.surplus} grams too much</h3> : <NoDataScreen />}
            {isLoading && <Skeleton />}
        </div>
    </AlertDescription>
</Alert>

}
Enter fullscreen mode Exit fullscreen mode

The mistake is that if the isLoading expression is true, the NoDataScreen component will be displayed along with the skeleton, because if isLoading is true, data is implicitly evaluated as false.

It's not a big deal, let's fix it:

function FoodAlert() {
const {data, isLoading} = useData();

return <Alert>
    <AlertTitle>Too much</AlertTitle>
    <AlertDescription>
        <h2>It seems to be enough</h2>
        <div>
            // that's it
            {data && !isLoading ? 
            <h3>you put on {data.surplus} grams too much</h3> 
            : 
            <NoDataScreen />}
            {isLoading && <Skeleton />}
        </div>
    </AlertDescription>
</Alert>

}
Enter fullscreen mode Exit fullscreen mode

Now, we’ve certainly fixed the bug, but don’t you think the component is a bit too verbose?

For my cooking recipe app, which is purely for educational purposes, it’s not really worth giving in to this kind of reasoning, I admit. But let’s say it’s no longer a recipe app but a large banking UI that needs to be easily scalable.

Component composition + early return = the magic formula

You might have expected me to talk about a revolutionary method that would solve our situation, but not at all. The solution has always been there; it’s about breaking down your UI into components. This is one of the fundamentals of the ReactJS library philosophy. You can explore the topic Right here.

In our case, I divided the FoodAlert component into two:

Image description

Here's what it looks like in code:

function Layout({children}) {

    return <Alert>
    <AlertTitle>Too much</AlertTitle>
    <AlertDescription>
        <h2>It seems to be enough</h2>
        <div>{children}</div>
    </AlertDescription>
</Alert>
}

function FoodAlert() {
const {data, isLoading} = useData();

return <Layout>
        {data && !isLoading ? 
        <h3>you put on {data.surplus} grams too much</h3> 
        : 
        <NoDataScreen />}
        {isLoading && <Skeleton />}
</Layout>

}
Enter fullscreen mode Exit fullscreen mode

And that's it for this first step of refactoring. We still haven't addressed the verbosity issue caused by the overuse of conditional rendering.

Better done now than later

This is where the early return comes in to save us from headaches. Here's how it translates into code:

function FoodAlert() {
const {data, isLoading} = useData();

if(isLoading) {
    return <Layout>
        <Skeleton />
    </Layout>
}

if(!data) {
    return <Layout>
        <NoDataScreen />
    </Layout>
}

return <Layout>
        <h3>you put on {data.surplus} grams too much</h3> 
</Layout>
Enter fullscreen mode Exit fullscreen mode

The component is easier to read, isn't it?

Top comments (0)