Do You Make These 7 Common Mistakes In React?

All developers who learn React make huge amounts of mistakes while learning the technology. Sometimes we don’t even know that we're making these mistakes. If you will become an awesome React developer you need to learn about these mistakes, avoid them, and code according to the best practices. In this article, I've thought to show some of the common mistakes, a lot of which I'm sure you have made or are currently making. Let's make them right.

First off, what are we even talking about ?

reactImage.jpg

What is React?

React is a free and open-source front-end JavaScript library for building user interfaces based on UI components. It is maintained by Facebook(now known as Meta) and a community of individual developers and companies. It allows developers to build fast user interfaces for websites and applications. Some outstanding reasons why we use React.

  • High performance reinforced by virtual DOM.
  • Reusability of components.
  • Vast and supportive community.
  • The power of Flux and Redux.
  • Since it uses JSX, anyone who knows HTML can easily learn it.
  • Unique react Hooks

Now, let’s dive into the mistakes most junior developers make and how we can correct them.

Let's take for example, a piece of state called number in your component.

const [number, setNumber] = useState(0);

Now, we are going to update that state and access it in the next line.

setNumber(5);
console.log(number);

The reason?

We should know that the updating function for number (here setNumber) is an asynchronous function. Since that function is the asynchronous controller, it will not hold until it updates. It will go to the next line and console the value of number (It will console 0 since the number is not updated 5 yet). So, If you are writing another statement using the updated value of number below that setNumber statement, your logic will be completely wrong.

How we can solve this for functional components, is by changing our updating function syntax to suit a more functional approach. This way:

setNumber(() => 5);

This method allows react to make the update immediately it comes across the piece of code.

The full and correct code snippet would look like this:

import { useState } from "react";

function App() {
  const [number, setNumber] = useState(0);

  const handleClick = () => {
    setNumber(() =>  5);
    console.log(number)
  };

  return (
    <>
      <h2>Number : {number}</h2>
      <button onClick={handleClick}>Set Number</button>
    </>
  );
}

export default App;

2.) How to initialize a state correctly [For Objects]

This is also a common mistake that some junior developers make. They initialize a state without a default value. For a single integer or string, this might not spring up an issue. But if you are initializing an object you must mention the default values. Otherwise, an error will occur when accessing the property of that object. Let’s use an object called user.

If you are initializing the object this way.

const [user, setUser] = useState();

Then somewhere else you assign a value to it.

setUser({
  name: "Koliko",
  age: 21,
  friends: ["Sparkles", "Maureen", "Khadeejah"]
});

If you then try accessing the object properties like this you will get an error.

<h2>name : {user.name}</h2>

The error will say this:

errorImage.png

There are two things you can do to make this right:

1) Add && before access

<h2>name : {user && user.name}</h2>

2) Add ?. when accessing

<h2>name : {user?.name}</h2>

But, I recommend you add a default value when initializing. You can add expected properties with an empty value.

const [user, setUser] = useState({
   name: "",
   age: "",
   friends: [],
});

3.) Updating an object

Here we'll look at how to update an object in a proper way. Let’s take the previous user object with initial values.

const [user, setUser] = useState({
  name: "Koliko",
  age: 21,
  friends: ["Sparkles", "Maureen", "Khadeejah"]
});

Add an input field with a button to change the name of the user object.

import { useState } from "react";

function App() {
  const [user, setUser] = useState({
  name: "Koliko",
  age: 21,
  friends: ["Sparkles", "Maureen", "Khadeejah"]
});
  const [input, setInput] = useState("");

  const handleClick = () => {

   // update the object here

  };
  return (
    <>
      <h2>name : {user.name}</h2>
      <h2>age : {user.age}</h2>
      <h2>friends :</h2>
      <ul>
        {user.friends?.map((friend) => (
          <li key={friend}>
            <h4>{friend}</h4>
          </li>
        ))}
      </ul>

      <input
        type="text"
        placeholder="Enter new name"
        onChange={(e) => setInput(e.target.value)}
      />
      <button onClick={handleClick}>Click</button>
    </>
  );
}
export default App;

First of all, let's look at the wrong ways some developers do this.

setUser(input);

or

setUser({name : input});

This will replace the object and assign the input we enter here. That is not what we should do. This is how it updates correctly.

setUser((prevState) => ({ ...prevState, name: input }));

Like I've stated earlier, the updating function (setUser) is changed to a more functional syntax approach and takes in an argument which is the up-to-date value of the previous state at the time of running the code.

4.) Create an object instead of separate states

In every web application, we use objects. Some developers define separate states for the property of an object. It takes lots of time and reduces the code readability. Imagine, we have a user in our application and we create a form to get user details. what are you going to use to store these user details?

In separate states like this:

const [fName, setFName] = useState("");
const [lName, setLName] = useState("");
const [email, setEmail] = useState("");
const [age, aetAge] = useState("");
const [city, setCity] = useState("");
const [gender, setGender] = useState("");
const [password, setPassword] = useState("");

Nope… You should create this using one state, this way:

const [user, setUser] = useState({
    fName: "",
    lName: "",
    email: "",
    age: "",
    city: "",
    gender: "",
    address: "",
    password: "",
});

5.) Create a single onChange function for all inputs in a form

Let’s take the above scenario. We can create a form to get that user details. After which we'll be creating onChange functions for those input fields.

<input type='text' name="fName" />
<input type='text' name="lName" />
<input type='text' name="email" />
<input type='text' name="age" />
<input type='text' name="city" />
<input type='text' name="gender" />
<input type='text' name="address" />
<input type='password' name="password" />

Are you gonna create separate onChange functions?

onChange={(e) => setUser((prevState)=>({ ...prevState, fName: e.target.value }))}
onChange={(e) => setUser((prevState)=>({ ...prevState, lName: e.target.value }))}
onChange={(e) => setUser((prevState)=>({ ...prevState, email: e.target.value }))}
....likewise

This is not good. You can use a better way to do this. Create one onChange function for all input fields. You need to add the same property name of the user to the name property of the input tag.

const handleChange = (e) => {
setUser((prevState) => ({...prevState,[e.target.name]:e.target.value  }));
};

Here is the full code snippet for this:

import { useState } from "react";

function App() {
  const [user, setUser] = useState({
    fName: "",
    lName: "",
    email: "",
    age: "",
    city: "",
    gender: "",
    address: "",
    password: "",
  });

  const handleChange = (e) => {
    setUser((prevState) => ({ ...prevState, [e.target.name]: e.target.value }));

  };

  return (
    <div>
      <form>
        <input type="text" onChange={handleChange} name="fName" placeholder="fName" />
        <input type="text" onChange={handleChange} name="lName" placeholder="lName" />
        <input type="text" onChange={handleChange} name="email" placeholder="email" />
        <input type="text" onChange={handleChange} name="age" placeholder="age" />
        <input type="text" onChange={handleChange} name="city" placeholder="city" />
        <input type="text" onChange={handleChange} name="gender" placeholder="gender" />
        <input type="text" onChange={handleChange} name="address" placeholder="address" />
        <input type="password" onChange={handleChange} name="password" placeholder="password" />
      </form>
      <button >Submit</button>
    </div>
  );
}

export default App;

6.) Direct DOM manipulation

Have you written code like this before:

function App() {
   const handleClick = () => {
       const menu = document.querySelector(".menu");
       menu.classList.add("color");
   }
   return (
        <>
        <div className="menu">Sample Text</div>
        <button onClick={handleClick}>Click</button>
        </>
   );
}

The problem?

This is very common among new react developers. We shouldn't do direct DOM manipulation in react. Instead of accessing DOM elements and adding classes to them, we can use state in our react component for this purpose. It will get harder to test, harder to debug, and harder to think about if the application mixes up the state inside of the DOM.

Here's, a possible solution for this. The same task is done without using document.querySelector.

import { useState } from 'react';
import './App.css'
function App() {
    const [isColored, setIsColored] = useState(false);
    const handleClick = () => {
         setIsColored(() => true);
    }
    return (
       <>
       <div className={isColored ? "color": "" + "menu" }>Sample     Text</div>
       <button onClick={handleClick}>Click</button>
       </>
    );
}

7.) useState vs useReducer (When to use?)

Is it a constant practice to use useState everywhere when we need a state? The answer is no. Sometimes we have a better option instead of using useState. It’s useReducer . Of course, there is no rule that you should use useReducer instead of useState or it’s not a mistake if you still use it. But in some specific situations, useReducer is more advantageous.

For example, think you have a more complex object that has different properties like arrays, and nested objects.

const [post, setPost] = useState({
   title: "",
   description: "",
   date: "",
   category: "",
   image: [],
   tag: [],
   owner: {
      name: "",
      email: "",
   }
});

Then, it’s better to use a reducer because when you update different properties, it’s gonna be really messy here. All properties here are not strings or numbers like in the previous examples, so we can't update them in one function. Creating a useReducer hook and using different actions for each property, might be more useful here. Hence, It’s better to use useReducer .

sheeessssshh!!!

We've come to the end of this article, I've pointed out 7 common mistakes a lot of junior developers make when working with React, I made a couple of them myself... Lol.

Please let me know your thoughts in the comments. Engage, like, share, and feel free to point out more mistakes that are not present in this post. Let's all learn and grow together !!

SUBSCRIBE to my newsletter to receive my articles directly in your mail ;-)

### See you in the next post :)

Your friend in progress,

CodeProphet.

paul-pastourmatzis-8kDOOrs608I-unsplash.jpg

Did you find this article valuable?

Support Emmanuel Obi by becoming a sponsor. Any amount is appreciated!