DEV Community

Cover image for ✨ Conditional rendering in React with finesse
Brett Thurston
Brett Thurston

Posted on

✨ Conditional rendering in React with finesse

So if you've spent a measure of time with React you'll come across the scenario of needing to render an element based on a condition.

For example, what if you had a component that counted something. And you wanted to show the actual count in a component. However, if it ever dropped below 1, you might want show a message in its place. Informing the user something or presenting a new call to action to do something else.

You could write it in a ternary operator like this:

import { useState } from "react";
import RenderIf from "components/RenderIf";

export const Sample = () => {
  const [count, setCount] = useState(2);
  const increment = () => {
    let newCount = count;
    setCount((newCount += 1));
  };
  const decrement = () => {
    if (count === 0) return;
    let newCount = count;
    setCount((newCount -= 1));
  };
  return (
    <>
      <button onClick={increment}>Add</button>
      <button onClick={decrement}>Subtract</button>
       {count > 0 
           ? <p>I have {count}, and that's pretty cool.</p>
           : <p>Sorry, I'm all out.</p>
        }
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

This works OK, but in my opinion doesn't read as easy as another option. What could a component look like to handle this use case?

Proposal

We can build a component that renders the content it wraps based on a condition we feed it. If that condition isn't true then we'll render something else. This will handle this use case with a little more finesse, IMO. 😎

First let's make a component called RenderIf. Below are the JSX and TypeScript version. Pick your poison.

JSX:

import { ReactNode } from "react";

const RenderIf = ({ children, isTrue, fallback }) => {
  return isTrue ? children : fallback;
};

export default RenderIf;
Enter fullscreen mode Exit fullscreen mode

TypeScript:

import { ReactNode } from "react";

type Props = {
  children: ReactNode;
  isTrue: boolean;
  fallback?: any;
};

const RenderIf = ({ children, isTrue, fallback }: Props) => {
  return isTrue ? children : fallback;
};

export default RenderIf;
Enter fullscreen mode Exit fullscreen mode

Esplaining what's happenin'

This component that we've made has 3 props being passed in:

  • children
  • isTrue
  • fallback

We destructure those props and pass them into the component. Children is whatever element this ** **component is wrapping. Then we pass the condition of when to render the wrapped element with the isTrue prop.

Whenever this condition is true (or truthy) it will render the wrapped element. If the condition is NOT true, then it renders whatever we pass in the fallback argument.

In TypeScript I've set this to be an optional argumentin the type of Props. Why? I may not want to always pass a fallback element. So if I pass no fallback argument prop then will return undefined and a blank component will render.

In the JSX version of , this happens naturally.

So your fallback argument can be a message saying, 'Hey you're out of counts' or it could be a button to buy more counts. You get the idea.

Jerry Maguire GIF by Jerology - Find & Share on GIPHY

Discover & share this Jerology GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.

favicon giphy.com

Example use in an app:

import { useState } from "react";
import RenderIf from "components/RenderIf";

export const Sample = () => {
  const [count, setCount] = useState(2);
  const increment = () => {
    let newCount = count;
    setCount((newCount += 1));
  };
  const decrement = () => {
    if (count === 0) return;
    let newCount = count;
    setCount((newCount -= 1));
  };
  return (
    <>
      <button onClick={increment}>Add</button>
      <button onClick={decrement}>Subtract</button>
      <RenderIf isTrue={count > 0} fallback={<p>Sorry, I'm all out.</p>}>
        <p>I have {count}, and that's pretty cool.</p>
      </RenderIf>
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

Go build some stuff

So now you've got a handy component you can use over and over again to render conditional elements in React. Maybe you want to extend this component to do other things too. What else could you see it do? Let me know what you think and if you'd take a different approach.

Good luck and happy building. 🔨

Tom Hanks Hello GIF - Find & Share on GIPHY

Discover & share this Hello GIF with everyone you know. GIPHY is how you search, share, discover, and create GIFs.

favicon giphy.com

Discussion (0)