Conditional Rendering of Components in React

ยท

6 min read

I've been working through the Epic React course from Kent C. Dodd over this holiday season ๐ŸŽ„

It's interesting seeing how I code things while I "try it out", then compare it to how Kent codes things in his solutions. One difference I wanted to share was around methods to conditionally rendering within components.

Let's imagine we have a component that allows you to search for pokemon. It has the following states:

  • Idle upon arrival to the page
  • Pending after submitting a search
  • A results view if proper data is returned
  • An error view if something goes wrong

We can use conditional rendering to display different content depending on what state the page is in.

Pseudocode Example

The skeleton below shows the `state passed into the component and the four different resulting states that are expected.

export const ConditionallyRendered = ({ state }) => {
    return (
        <div>
            {/* Display idle state when first loaded (state is "idle") */}
            {/* Display pending message if waiting for response (state is "pending") */}
            {/* Display the Pokemon if successfully received (state is "resolved") */}
            {/* Display an Error Message if there's an error (state is "rejected") */}
        </div>
    );
};

Let's first take a look at rendering different JSX depending on the states.

Approach 1: JavaScript Rendering Different JSX

Here, outside of the return (<jsx/>) block, we use an if/else statement to decide what to render.

export const ConditionallyRendered = ({ state }) => {
    if (state === "idle") {
        // Display idle state when first loaded.
        return "Submit a pokemon";
    } else if (state === "pending") {
        // Display pending message if waiting for response.
        return <PokemonInfoFallback name={pokemonName} />;
    } else if (state === "resolved") {
        // Display the Pokemon if successfully received.
        return <PokemonDataView pokemon={pokemon} />;
    } else if (state === "rejected") {
        // Display an Error Message if there's an error.
        return <ErrorMessage error={error} />;
    }
    return <div></div>;
};

You could easily use a case/switch statement if you'd prefer.

The alternative I will show sounds like a similar method, but there is a nuanced difference.

Approach 2: JavaScript in JSX Rendering Different JSX

Here we jump right into JSX, then we drop into JavaScript and use some simple logic to decide what to render.

export const ConditionallyRendered = ({ state }) => {
    return (
        <>
            {/* Display idle state when first loaded. */}
            {state === states.idle && "Submit a pokemon"}
            {/* Display pending message if waiting for response. */}
            {state === states.pending && <PokemonInfoFallback pokemon={pokemon} />}
            {/* Display the Pokemon if successfully received. */}
            {state === states.resolved && <PokemonDataView pokemon={pokemon} />}
            {/* Display an Error Message if there's an error. */}
            {state === states.rejected && <ErrorMessage error={error} />}
        </>
    );
};

It's a bit weird when you first see it. We are taking advantage of the fact that cond1 && cond2 will stop evaluating at the && if cond1 is falsy. That means cond2 will never be reached. In our case, the JSX will not be rendered.

In the case that cond1 is truthy, cond2 will be evaluated. In our case, the JSX will be rendered.

Pros and Cons

While I like the cleaner look to Appoach 2, if you think about it, there's a potential buggy state we could achieve with that.

  • Using an if/then statement like in Appoach 1, one and only one return (<jsx/>) block will be reached.
  • Using the && login in Approach 1, depending on the logic to the left of && (called cond1), you could accidentally render two different states.

Maybe this is a pro for you though. Perhaps you want to be able to render any number of states depending on complex conditioning. In this case Approach 2 is definitely the way to go.

Another reason to go with Approach 2 is if there is content you want on the page regardless of the state (a title, the data, etc). If you want this, you'll want to extract these conditional states into separate components to use Approach 1.

However, in the example we are looking at here, we only want one state to show at a time and there is no other content displayed in the component. This makes it a good candidate for Approach 2

Conclusion

So, between Kent and I, who chose Approach 1 and who chose Approach 2 in the ` Epic React course? Hopefully, I keps an unbiased approach while writing this article and you'll just need to buy his course to find out! ๐Ÿ˜œ