avatarKliton Bare

Summary

The article discusses a method for improving the readability and maintainability of React code by using if-else components, specifically through the react-if library, to handle conditional rendering more effectively.

Abstract

The article addresses the challenge of conditional rendering in React, particularly in large components, where traditional methods like ternary operators can lead to unreadable code. The author shares their initial frustration with the complexity that conditional logic introduces in React components, especially when dealing with multiple conditions. The solution proposed involves the use of the react-if library, which provides If, Then, Else, Switch, Case, and Default components to streamline conditional rendering. By refactoring complex components with these specialized components, the code becomes more expressive and easier to maintain. The author illustrates this with examples, showing how the new approach enhances clarity even when the codebase grows. Additionally, the article suggests that this method can be extended to handle multiple conditions using Switch/Case/Default components, offering a robust solution for complex rendering logic. The author concludes by expressing satisfaction with this approach in their own projects and encourages readers to adopt it for cleaner React code.

Opinions

  • The author initially disliked the complexity of conditional rendering in React but found a solution that improved code readability.
  • Large components with nested conditional logic are seen as difficult to read and maintain.
  • The react-if library is recommended as a way to make conditional rendering more readable and maintainable.
  • The author believes that using If, Then, Else components can make the code more expressive, despite increasing its length.
  • The article suggests that a simple if-else structure may not be sufficient for complex scenarios, advocating for the use of Switch/Case/Default components.
  • The author and their team have personally adopted this approach and find it effective and satisfactory for their projects.
  • The author encourages readers to try out the techniques discussed in the article to improve their own React codebases.

Write More Readable React Code By Using If-Else Components

Avoid using ternary operators that make your code unreadable

I used to hate how React conditional rendering messed up my code, but then I found a way of doing it that made things much easier.

ReactJS official documentation explains how to do conditional rendering in React.

But in large projects or components, the code is not very readable and maintainable.

The problem

Conditional rendering in React can make the code hard to read and maintain.

If your component is small enough, you can do something like this:

Let’s say we have a component that renders a button. The button should be rendered only if the user is logged in. Otherwise, it should not be rendered.

const Button = ({userIsLoggedIn}) => {
  if (userIsLoggedIn) {
    return <button>Click me</button>
  } else {
    return null
  }
}

And this is a great way to handle conditional rendering because we are just returning different things based on the condition.

But what if your component is large and has a lot of code?

It will be hard to read and maintain.

Let’s say we have a complex component that needs to render a button, a form, and a list of items.

The button should be rendered only if the user is logged in.

Otherwise, it should not be rendered.

Note: some people may say that I need to split the component into smaller components.

But this is just an example needed to point out the problem.

const ComplexComponent = ({ userIsLoggedIn, items }) => {
  // [state code here]

  return (
    <div>
      <h1>Complex Component</h1>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          name="name"
          value={form.name}
          onChange={handleFormChange}
        />
        <input
          type="text"
          name="age"
          value={form.age}
          onChange={handleFormChange}
        />
        <button type="submit">Submit</button>
      </form>
      <ul>
        {items.length > 0 ? (
          items.map((item, index) => (
            <li key={index}>
              {item.name} - {item.age}
              <button onClick={() => handleDelete(index)}>Delete</button>
            </li>
          ))
        ) : (
          <div>No items</div>
        )}
      </ul>
      {items.length <= 0 ? (
        <button>Load from CSV</button>
      ) : (
        <button>Clear All</button>
      )}
    </div>
  );
};

As you can see, the code is not very readable and maintainable because of the conditional rendering.

The code that ruins readability is the following:

<ul>
  {items.length > 0 ? (
    items.map((item, index) => (
      <li key={index}>
        {item.name} - {item.age}
        <button onClick={() => handleDelete(index)}>Delete</button>
      </li>
    ))
  ) : (
    <div>No items</div>
  )}
</ul>;

And also this one

{
  items.length <= 0 ? (
    <button>Load from CSV</button>
  ) : (
    <button>Clear All</button>
  );
}

The solution: If/Else component

We can try to create a component that handles the conditional rendering for us to make the code more readable and expressive.

We’re not going to recreate the wheel here, so we’re going to use the library react-if.

In this tutorial, we will use the If, Then, Else components from the library.

Now we can write the code like this:

import { If, Then, Else } from 'react-if'

const ComplexComponent = ({userIsLoggedIn, items}) => {
  // [state code here]

  return (
 <div>
  <h1>Complex Component</h1>
  <form onSubmit={handleSubmit}>
    <input
      type="text"
      name="name"
      value={form.name}
      onChange={handleFormChange}
    />
    <input
      type="text"
      name="age"
      value={form.age}
      onChange={handleFormChange}
    />
    <button type="submit">Submit</button>
  </form>
  <If condition={items.length > 0}>
    <Then>
      <ul>
        {items.map((item, index) => (
          <li key={index}>
            {item.name} - {item.age}
            <button onClick={() => handleDelete(index)}>Delete</button>
          </li>
        ))}
      </ul>
    </Then>
    <Else>
      <div>No items</div>
    </Else>
  </If>
  <If condition={items.length <= 0}>
    <Then>
      <button>Load from CSV</button>
    </Then>
    <Else>
      <button>Clear All</button>
    </Else>
  </If>

Now the code is a little bit longer but I think is more readable and maintainable.

Other useful components: Switch/Case/Default

Sometimes a simple if/else is not enough.

We need to handle more than two conditions

We can use the Switch, Case, and Default components from the library.

Let’s create now a component that renders an age group based on the age of the user.

import { Switch, Case, Default } from "react-if";

const AgeDescription = ({ age }) => {
  return (
    <Switch>
      <Case condition={age < 18}>
        <div>Too young</div>
      </Case>
      <Case condition={age >= 18 && age < 30}>
        <div>Young</div>
      </Case>
      <Case condition={age >= 30 && age < 50}>
        <div>Old</div>
      </Case>
      <Default>
        <div>Too old</div>
      </Default>
    </Switch>
  );
};

I know, is a very simple example, but I hope you get the idea.

I and my team are using this approach in our projects and we are very happy with it.

I hope you found this tutorial useful. Thanks for reading.

Here are some other articles that I wrote that I think you can find useful

Programming
React
JavaScript
Software Development
Coding
Recommended from ReadMedium