Common Mistakes React Developers Make – And How to Fix Them

Yogesh Chavan - May 5 '21 - - Dev Community

In this article, we'll see some of the common mistakes made by React developers and ways to avoid them.

So let's get started.

Don't Forget that Every Route Change Mounts and Unmounts a Component

Whenever we're using routing in React application, we declare routes inside the Switch component so at a time only one component with the matching route is displayed.

Therefore, whenever we go from one route to another, the previously displayed component is unmounted and the component with the new matching route is mounted.

If you need to persist some data across route change, you need to declare it in the component which encapsulates the routes such as the App component in the following Code Sandbox or some other way of persisting data like using local storage or session storage

As you can see in the above Code Sandbox, whenever we change the route by clicking on the links, we get the corresponding console.log displayed on the console to indicate that the previous component is unmounted and a new component is mounted.

Don't Use the Wrong setState Syntax

Whenever we declare a state inside the class-based component, it's always an object like this:

this.state = {
   counter: 0
}
Enter fullscreen mode Exit fullscreen mode

so whenever we use the updater form of setState syntax to update the state, it looks like this:

this.setState((prevState) => {
  return {
    counter: prevState.counter + 1
  };
});
Enter fullscreen mode Exit fullscreen mode

As the state is an object, prevState is also an object so we access the counter using prevState.counter.

But when we're using functional component using React Hooks the state can be an object or a non-object value as shown below:

const [counter, setCounter] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Here, the value of counter is not an object but it's a number so to update the state using updater syntax we write the code like this:

setCounter((prevCounter) => prevCounter + 1);
Enter fullscreen mode Exit fullscreen mode

Here, the prevCounter is a number so we don't use prevCounter.counter but just prevCounter or it can be simplified as shown below:

setCounter((counter) => counter + 1);
Enter fullscreen mode Exit fullscreen mode

Check out my this article for complete introduction to React State

Don't Call Hooks from Class Components

Starting with React version 16.8.0, React has introduced Hooks that allow us to write better React code
and make use of state and component life cycle methods inside functional components.

Check out my this article for an Introduction to React Hooks.

To make coding easy, there are many hooks provided by React like:

  • useParams hook to access URL parameters when using React Routing
  • useHistory hook to get access to history API inside any component
  • useRef hook to get access to DOM element

and many other hooks.

But all of these hooks which usually starts with the use keyword work only inside the functional components.

If you're having a class-based component then you can't use these hooks. You need to refactor your code to convert it to functional components otherwise, you might get an error as can be seen in the below screenshot:

hook_error.png

Don't Forget to Add a Key Prop When Using the Array map Method

Take a look at this Code Sandbox Demo.

Here, for displaying a list of items, we're using the following code:

const Items = ({ items }) => (
  <ol>
    {items.map((item) => (
      <Item item={item} />
    ))}
  </ol>
);
Enter fullscreen mode Exit fullscreen mode

In React, for displaying a list of items stored in an array, usually, the array map method is used.

But as soon as you add an item to the list in the above Code Sandbox, you will see a missing key warning displayed in the console.

missing-key.gif

This is because every time you're using the array map method to loop over the items, you need to provide a unique key prop which React uses to identify which elements on the screen need to be re-rendered and adding key prop helps to avoids unnecessary re-rendering in your app.

Here's an updated Code Sandbox Demo with the added key prop.

Here, we've provided a unique key prop to each element we're looping over like this:

<Item item={item} key={index} />
Enter fullscreen mode Exit fullscreen mode

Therefore, If you try adding some items, you will not get any warning in the console.

added-key.gif

Note: In the above code, as the elements not re-ordered or removed, using index as key works fine but If you're removing or changing the displayed elements order then you need to provide a unique key instead of using index.

Don't Use Inline Functions the Wrong Way

Take a look at this Code Sandbox Demo.

Here, we've added some items to the state:

const [items, setItems] = useState(["one", "two"]);
Enter fullscreen mode Exit fullscreen mode

and we're looping over them to display on the screen:

{items.map((item, index) => (
  <li key={index}>
    {item} <button onClick={handleRemoveItem(item)}>Remove</button>
  </li>
))}
Enter fullscreen mode Exit fullscreen mode

If you check the application, you will see that no items are displayed on the screen and adding new items also does not work as can be seen below:

wrong_inline.gif

This is because of the onClick handler for the button:

<button onClick={handleRemoveItem(item)}>Remove</button>
Enter fullscreen mode Exit fullscreen mode

Here, we're calling the handleRemoveItem method when the user clicks on the button but the way we're calling the method is wrong.

So If we don't need to pass any parameter we use the following syntax:

<button onClick={handleRemoveItem}>Remove</button>
Enter fullscreen mode Exit fullscreen mode

But later If we decide to pass some parameter to the function, we need to call the handler inside inline function like this:

<button onClick={() => handleRemoveItem(item)}>Remove</button>
Enter fullscreen mode Exit fullscreen mode

Most React developers forget to add an inline function and then it takes hours of debugging to understand why something does not work.

Here's an updated working Code Sandbox Demo.

Thanks for reading!

Starting with ES6, there are many useful additions to JavaScript like:

  • ES6 Destructuring
  • Import and Export Syntax
  • Arrow functions
  • Promises
  • Async/await
  • Optional chaining operator and a lot more.

You can learn everything about all the ES6+ features in detail in my Mastering Modern JavaScript book.

Check out free preview contents of the book here.

Also, you can check out my free Introduction to React Router course to learn React Router from scratch.

Want to stay up to date with regular content regarding JavaScript, React, Node.js? Follow me on LinkedIn.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .