DEV Community

Cover image for How to Write Cleaner React code
Aditya Tyagi
Aditya Tyagi

Posted on • Originally published at adityatyagi.com

How to Write Cleaner React code

After getting my hands dirty with over 10 production level React projects, one thing that was consistent with most of them was the use of unnecessary HTML elements/tags. It is highly important that your code is easier to maintain, write, read and debug. As a thumb rule, you can follow this to identify if your code follows clean code guidelines:

Clean Code in React by Aditya Tyagi.jpeg

These tags were polluting the DOM for no reason at all. But they introduced these tags to overcome the drawback of JSX in React. The drawback is that JSX should always return a single root HTML element.
In other words, this is invalid JSX:

// The parenthesis helps to write multi-line HTML
const element = (

  // 1st div block
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>

  // 2st div block
  <div>
    <h1>Sibling element</h1>
    <h2>I will break JSX element</h2>
  </div>
);
Enter fullscreen mode Exit fullscreen mode

Because of this drawback, many developers add div tags to wrap enormous blocks of code. Hence, resolving the drawback of JSX.

const element = (

  // The wrapper
  <div>

      // 1st div block
      <div>
        <h1>Hello!</h1>
        <h2>Good to see you here.</h2>
      </div>

      // 2st div block
      <div>
        <h1>Sibling element</h1>
        <h2>I will break JSX element</h2>
      </div>

  </div>
);
Enter fullscreen mode Exit fullscreen mode

Now, this works for minor projects. I am guilty of going this route as well. Won’t lie. But then as I started working on gigantic React oriented projects, I found the DOM code filled with div tags throughout. This sooner or later resulted in a “div soup“

div soup in react.png

What is a div soup?

An example will make it much clearer than me slapping the keyboard to vomit out explanatory paragraphs!

Consider this piece of React code:

return (
    // This div does nothing but wraps the two children
    <div>
      <h1>This is heading</h1>
      <h2>This is a sub-heading</h2>
    </div>
  )
Enter fullscreen mode Exit fullscreen mode

The result of this in the DOM will be:

DOM.png

This is a minor example. Real React apps are way more complex. You can have a deeply nested parent-children relationships between components. For example:

  return (
    <div>
      <h1>This is heading</h1>
      <h2>This is a sub-heading</h2>
      <Child1>
        <Child2>
          <Child3>
            <Child4/>  
          </Child3>
        </Child2>
      </Child1>
    </div>
  )
Enter fullscreen mode Exit fullscreen mode

Where the children are:

// Every React JSX element inherently receives the "props" argument
const Child1 = (props) => (
  <div>
    <h3>I am child 1</h3>
    {/* Anything that is passed between <Child1> and </Child1> */}
    {props.children}
  </div>
);

const Child2 =  (props) => (
  <div>
    <h3>I am child 2</h3>
    {props.children}
  </div>
);

const Child3 = (props) => (
  <div>
    <h3>I am child 3</h3>
    {props.children}
  </div>
);

const Child4 = () => (
  <div>
    <h3>I am child 4</h3>
  </div>
);
Enter fullscreen mode Exit fullscreen mode

This will produce DOM:

image-1.png

If you carefully check the generated DOM, you’ll see a ton of div tags which serves has no purpose but to wrap the code and overcome the JSX limitation. Eventually, this will cause a div soup.

This can exponentially increase the time of debugging and hence can affect faster delivery and bug-fixes!

Ratio-of-Time-Spent-Reading-Code-Versus-Writing.png

Avoid a DIV soup

Eagle-eyed readers must have noticed the solution in the problematic code itself. All we have to do is create a wrapper React component which returns the passed component without the div

// Wrapper component that returns any DOM element passed between <Wrapper> and </Wrapper>
// The props inherently have the children property on it
// All react JSX elements should be Capitalized as a naming convention 

const Wrapper = (props) => {
  return props.children;
}
Enter fullscreen mode Exit fullscreen mode

Refactoring the previous code:

// Every React JSX element inherently receives the "props" argument
const Child1 = (props) => (
  <Wrapper>
    <h3>I am child 1</h3>
    {/* Anything that is passed between <Child1> and </Child1> */}
    {props.children}
  </Wrapper>
);

const Child2 =  (props) => (
  <Wrapper>
    <h3>I am child 2</h3>
    {props.children}
  </Wrapper>
);

const Child3 = (props) => (
  <Wrapper>
    <h3>I am child 3</h3>
    {props.children}
  </Wrapper>
);

const Child4 = () => (
  <Wrapper>
    <h3>I am child 4</h3>
  </Wrapper>
);
Enter fullscreen mode Exit fullscreen mode

and

return (
    <Wrapper>
      <h1>This is heading</h1>
      <h2>This is a sub-heading</h2>
      <Child1>
        <Child2>
          <Child3>
            <Child4/>  
          </Child3>
        </Child2>
      </Child1>
    </Wrapper>
  )
Enter fullscreen mode Exit fullscreen mode

This will remove the unnecessary div tags and hence prevent the soup!

Clean React Code.png

React Fragments

It will be difficult and an added effort to introduce this Wrapper component in every React project, and we developers try to avoid exactly such situations.

Introducing React Fragments.

According to the official documentation:

A common pattern in React is for a component to return multiple elements. Fragments let you group a list of children without adding extra nodes to the DOM.

You can do this in two ways:

  1. Using React.Fragment
  2. Using a short syntax of React.Fragment which is <> and </>

Let me show you via our code above with this:

return (
    <React.Fragment>

      <h1>This is heading</h1>
      <h2>This is a sub-heading</h2>
      <Child1>
        <Child2>
          <Child3>
            <Child4/>  
          </Child3>
        </Child2>
      </Child1>

    </React.Fragment>
  )
Enter fullscreen mode Exit fullscreen mode

Using a short-hand is much better for lazy developers like me:

 return (
    <>

      <h1>This is heading</h1>
      <h2>This is a sub-heading</h2>
      <Child1>
        <Child2>
          <Child3>
            <Child4/>  
          </Child3>
        </Child2>
      </Child1>

    </>
  )
Enter fullscreen mode Exit fullscreen mode

The final code will look like this:


const Child1 = (props) => (
  <>
    <h3>I am child 1</h3>
    {/* Anything that is passed between <Child1> and </Child1> */}
    {props.children}
  </>
);

const Child2 =  (props) => (
  <>
    <h3>I am child 2</h3>
    {props.children}
  </>
);

const Child3 = (props) => (
  <>
    <h3>I am child 3</h3>
    {props.children}
  </>
);

const Child4 = () => (
  <>
    <h3>I am child 4</h3>
  </>
);
Enter fullscreen mode Exit fullscreen mode

This will help you get the same results, avoiding the div soup.

Avoid div soup.png

Top comments (0)