Conditional Rendering in React: Show and Hide Things the Easy Way

React.js Full Course: Beginner to Advanced · Start Here · 9 min read · Updated

Show the right screen

  1. A page that loads data is always in one of three situations.
  2. First check loading. If it is loading, return early with a loading message.
  3. Next check for an error. If there is one, show a clear message and a way to retry.
  4. Otherwise show the data. If the list is empty, show a helpful empty message.
  5. Early returns keep the code flat. Remember to make the left side of && a real true or false.

Real pages show different things at different times. A person who is signed in sees their name, and a visitor sees a Sign in button. A list that is empty shows a friendly message. A page that is loading shows a spinner. Showing different content depending on a condition is called conditional rendering. In React there is no special syntax for it. You use plain JavaScript, which makes it easy to learn.

Way 1: an if statement before the return

A component is a function, so you can use if before you return. This is the clearest way when the screens are very different.

function Greeting({ isLoggedIn }) {
  if (isLoggedIn) {
    return <h2>Welcome back!</h2>;
  }
  return <h2>Please sign in.</h2>;
}

When the first return runs, the function stops, so the second line is only reached when isLoggedIn is false. This idea is called an early return, and it keeps code flat and easy to read.

Way 2: the ternary operator

Inside JSX you cannot write an if statement, because curly braces accept only expressions. The ternary operator is an expression with three parts: condition ? valueIfTrue : valueIfFalse.

function Status({ isOnline }) {
  return (
    <p>
      The user is {isOnline ? 'online' : 'offline'}.
    </p>
  );
}

function Badge({ isOnline }) {
  return (
    <span className={isOnline ? 'badge green' : 'badge grey'}>
      {isOnline ? <b>Online</b> : <i>Offline</i>}
    </span>
  );
}

You can use a ternary for text, for attribute values, and for whole pieces of JSX. If you find yourself nesting one ternary inside another, stop: it becomes very hard to read. Use if or a small component instead.

Way 3: the && operator

When you want to show something or nothing, use &&. In JavaScript, a && b gives b if a is true, and gives a if it is false. React shows nothing for false, so this works as a simple “show this only if” rule.

function Inbox({ unread }) {
  return (
    <div>
      <h2>Inbox</h2>
      {unread > 0 && <p>You have {unread} new messages.</p>}
    </div>
  );
}

Way 4: save JSX in a variable

For bigger choices, you can pick the content first and then show it:

function Panel({ role }) {
  let content;
  if (role === 'admin') {
    content = <AdminTools />;
  } else if (role === 'editor') {
    content = <EditorTools />;
  } else {
    content = <p>You can only read.</p>;
  }
  return <section>{content}</section>;
}

Another handy way is an object that maps a value to a component:

const screens = {
  home: <Home />,
  about: <About />,
  contact: <Contact />,
};

function Page({ name }) {
  return screens[name] || <NotFound />;
}

The three screens every data page needs

When a page loads data, it is always in one of three situations: it is still loading, it failed, or it has data. If you forget one of them, people see a blank page or a crash. A good pattern is to handle the unusual cases first with early returns:

function JobList({ jobs, loading, error }) {
  if (loading) return <p>Loading jobs...</p>;
  if (error) return <p role="alert">Sorry, we could not load the jobs. Please try again.</p>;
  if (jobs.length === 0) return <p>No jobs yet. Add your first one!</p>;

  return (
    <ul>
      {jobs.map((job) => (
        <li key={job.id}>{job.title}</li>
      ))}
    </ul>
  );
}

Because each unusual case returns early, the last part of the function only has to think about the happy case. This is much easier to read than a deep chain of if and else. Also notice the empty state: an empty list is not an error, and a helpful message with a next step is kinder than a blank space.

Showing nothing

A component can return null to show nothing. This is useful when a component decides not to appear:

function Banner({ message }) {
  if (!message) return null;
  return <div className="banner">{message}</div>;
}

Hiding with CSS or removing from the page?

With conditional rendering, a hidden element is removed from the page, and any state inside it is lost. When it comes back, it starts fresh. If you want to keep the state, or want a fade animation, you can hide the element with CSS instead (for example the hidden attribute or display: none). Choose based on what you need:

  • Remove it (conditional rendering): saves work and memory, resets the state.
  • Hide it (CSS): keeps the state, allows animation, but the component still exists.

Choosing between the ways

  • Two very different screens: early return with if.
  • Choose between two small things inside JSX: ternary.
  • Show something or nothing: && with a true/false left side.
  • Many choices: a variable with if/else, a switch, or an object map.

Common mistakes

  • {count && <List />} when count can be 0. It shows 0. Use count > 0 &&.
  • Nested ternaries that nobody can read. Use if or split into components.
  • Trying to write {if (x) {...}} in JSX. Statements are not allowed inside braces.
  • Forgetting the empty and error cases for data pages.
  • Reading user.name when user can be null. Check user && first, or use user?.name.

The last item uses optional chaining, written ?.. It stops safely and gives undefined if the value before it is null or undefined, instead of crashing. It is very useful when data has not arrived yet.

Putting it together: a small account menu

Here is a menu that uses several of the ideas from this lesson at once: an early return, a ternary and &&.

function AccountMenu({ user, loading, unread }) {
  if (loading) return <p>Checking your account...</p>;
  if (!user) return <a href="/login">Sign in</a>;

  return (
    <div>
      <p>Hello, {user.name}!</p>
      {unread > 0 && <p role="status">You have {unread} new messages.</p>}
      {user.isAdmin ? <a href="/admin">Admin area</a> : <a href="/account">My account</a>}
    </div>
  );
}

Each line has one clear job. The first two lines handle the unusual cases and finish early. After that, the code only thinks about a signed-in user. This habit, handling the odd cases first, keeps components flat and easy to read, even when they grow.

Questions beginners often ask

Which way should I choose? Pick the one that makes the code easiest to read. A short ternary for text, && for show-or-nothing, and early returns for whole screens. If you cannot read your own condition in one go, split it into a variable with a clear name, such as const canEdit = user && user.isAdmin;.

Does hidden content still cost anything? Content that is not rendered costs nothing, because it is not in the page. Content hidden with CSS is still in the page, and its component still runs.

Can I render different components in a loop? Yes. Inside map, you can use a ternary or an object map to choose a component for each item, for example a Photo or a Video depending on the type field.

Is it fine to use switch? Yes. A switch before the return is good for many cases. Keep each case short, and move big pieces into their own components.

Your task

  1. Make a LoginButton that shows “Log in” when signed out and “Log out” when signed in, using a ternary and state.
  2. Make a Notice component that returns null when its message prop is empty.
  3. Make a UserList that shows Loading, an error message, an empty message, or the list, depending on three props.
  4. Test the zero trap: show a count with count && ... and then fix it.

How to check it worked

  • Each situation shows the right screen when you change the props by hand.
  • No stray 0 appears on the page.
  • No error in the console when the data is empty.

Summary

  • Conditional rendering is plain JavaScript: if, ternary ?: and &&.
  • Use early returns for loading, error and empty screens.
  • Make the left side of && a real true or false to avoid the stray 0.
  • Return null to show nothing, and use ?. to read values that may be missing.

Frequently asked questions

Can I use if inside JSX?

No, JSX curly braces accept expressions only. Use a ternary (condition ? a : b) or && inside JSX, or use if before the return.

Why does my page show a 0?

You wrote something like {count && <X />} and count was 0. React shows the number 0. Write {count > 0 && <X />}.

Does a hidden component keep its state?

If you remove it with conditional rendering, no, the state is lost. If you only hide it with CSS, the component stays and keeps its state.

What does ?. mean?

It is optional chaining. user?.name gives undefined if user is null or undefined, instead of crashing.