The React Tunnel Vision
Tags: webdev, javascript, react, css
Published: 2023-03-02 18:31:51

Are you tired of overcomplicating your React projects with excessive JavaScript? Well, so do I! 

After exploring countless codebases, One thing I've noticed as a web developer is the tendency to get caught up in the React way of doing things, I've named this as the "React tunnel vision." 

This phenomenon occurs when we become so focused on solving problems with React that we forget about other tools and solutions that may be better suited for certain tasks. This can lead to overcomplicating code, creating unnecessary abstractions, and sacrificing performance. 

As someone who has fallen victim to this tunnel vision, I've learned the importance of taking a step back and considering other options, such as using plain CSS for certain styling tasks, or using vanilla JavaScript for simple interactions.

Whether you're a seasoned developer or just starting out, these tips can give you a real advantage and improve your project's performance.

## Why does this happen?

This tunnel vision is not entirely our fault. Many times, we have tight deadlines and we simply do not have the luxury of experimenting with different approaches to solve layout problems. However, when we take a step back and consider using CSS, we can create more efficient and elegant solutions.

But that's not just it, for the sake of the readability and documentation of the codebase, having CSS being the only responsible of handling the styling and layouts can help a lot with the separation of concern.

As someone who has struggled with separating business logic from styling, I understand how frustrating it can be to have a tangled mess of code that leads to unnecessary re-renders. It's crucial to keep concerns separate to make code maintainable, easy to read, test, and modify.

In this post we are going to focus entirely on how CSS can help us solve many of the issues we tend to try solv

## The mistakes we make along the way

As someone who has worked with React components and CSS styling, I understand the struggle of trying to separate business logic from styling logic within the same component. It's all too easy to fall into the trap of using state and conditionals to toggle CSS styles, leading to tangled and hard-to-maintain code.

One great example is the simple problem of accordions

Imagine you have this page that may contain from one to several accordions, if you have more than 1 accordion, the accordions should show closed, but if only one accordion is being display then open it, there is no need for it to be hidden

This would be the classic react way of solving this issue

```react

import React, { useState } from 'react';
import Accordion from './Accordion';

const AccordionWrapper = ({ accordionItems }) => {
  const [openAccordionIndex, setOpenAccordionIndex] = useState(null);

  const handleAccordionClick = (index) => {
    if (openAccordionIndex === index) {
      setOpenAccordionIndex(null);
    } else {
      setOpenAccordionIndex(index);
    }
  };

  return (
    <div>
      {accordionItems.map((item, index) => (
        <Accordion
          key={index}
          title={item.title}
          content={item.content}
          isOpen={openAccordionIndex === index || (openAccordionIndex === null && index === 0)}
          handleClick={() => handleAccordionClick(index)}
        />
      ))}
    </div>
  );
};

export default AccordionWrapper;

```

I've seen code like this through dozens of codebases, and it's okay, if you wrote solutions like this, chances are you this is not the code that is holding back your app from being blazingly fast and performant, but starting to identify and prevent this overuse of JavaScript can really improve your potential as a front end engineer

Now... How should you really write this component?

```react

import React from 'react';

const Accordion = () => {
  return (
    <div>
      <input id="accordion" type="checkbox" name="accordion" defaultChecked />
      <label htmlFor="accordion">Accordion</label>
      <div className="accordion-content">
        {/* Accordion content here */}
      </div>
    </div>
  );
};

//And you can map this component without needing to pass any prop nor state!

export default Accordion;


```
And simply use CSS

```css

.accordion-wrapper {
  display: block;
}

input[type="checkbox"] {
  display: none;
}

label {
  display: block;
  padding: 10px;
  background-color: #eee;
  font-weight: bold;
  cursor: pointer;
}

input[type="checkbox"]:checked + label {
  background-color: #ccc;
}

.accordion-content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.5s;
}

input[type="checkbox"]:checked ~ .accordion-content {
  max-height: 1000px;
  transition: max-height 0.5s;
}

/* :only-child selector to open the only accordion by default */
input[type="checkbox"]:only-child:checked ~ .accordion-content {
  max-height: 1000px;
  transition: max-height 0.5s;
}

```

* Accordion is represented by an input checkbox and a corresponding label
* Label is styled like a button and toggles the checked state of the checkbox when clicked
* Accordion content is a div element with the class "accordion-content"
* Adjacent sibling selector (+) is used to style the label when checkbox is checked
* General sibling selector (~) is used to style the accordion content when checkbox is checked
* Max-height property controls height of accordion content
* Transition property creates smooth animation when accordion is opened or closed
* :only-child selector styles accordion content when it's the only child of the wrapper element
* Checkbox state determines if the accordion is open or closed by default

So, as you can see, we could manage both the open/close states for each individual accordion and also the condition that if we only rendered a single accordion, said accordion should be open by default. 

Little disclosure, I don't think you should handle every conditional rendering in react like this, obviously if you need to keep track of which accordions are open and then send that data over then a state is the obvious solution, but this is to prove that sometimes, you have to take a step back, try to get out of the react tunnel vision and reconsider if you can move some logic around and let CSS handle the rest.

## The conclusion

There could be many arguments for writing the accordion in the React way, and I agree. However, I want to stress the importance of avoiding the React/JavaScript tunnel vision. Sometimes, it's worthwhile to take a step back and consider whether CSS already offers an efficient solution to a given problem. By doing so, you may be able to optimize your project's performance and make it more effective. In short, by being mindful of these considerations and striking a balance between the use of CSS and React, you can create effective, performant, and maintainable components anywhere you go.