Don't use useEffect
Tags: react, javascript, hooks, frontend
Published: 2023-01-10 23:05:09

In this post We'll prove that in 90% of our components we don't need to write a useEffect ...

## First question, When does useEffect run?


```javascript
const User = ({name}) => { // 1
  const [initials, setInitials] = useState(""); // 2
  useEffect(() => {
    setInitials(name.split(" ").map(str => str.charAt(0))); // 4
  }, [name]);
  return (
    <p>{initials}</p> // 3
  );
};
```

React will render this component in this sequence:
1. Read the prop **_name_**, let's say it's value is **_"John Doe"_**.
2. Define the state called **_initials_** and give it the empty string as initial value.
3. Return the JSX with this initial value, So **_initials_** will be an **_empty string_**.
3. Run the function passed to the useEffect hook which sets the name to be _**"John Doe"**_
4. Return the new JSX which now has **_initials_** as **_JD_**


So our component already had the value **_"John Doe"_** from beginning, But useEffect made it render twice! ... Let's get rid of this additional render ...

```javascript
const User = ({name}) => { // 1
  const initials = name.split(" ").map(str => str.charAt(0)); // 2
  return (
    <p>{initials}</p> // 3
  );
};
```
Now React will
1. Read the value of **_name_**
2. Calculate **_initials_**
3. Return the JSX with the right value, Without the need of rendering the component again!


What if the previous component has more renders due to change in other props, It'll recalculate the initials in every new render, right? Yes, But instead of using a useEffect and putting the name in the dependency array ... We can easily use the useMemo hook not to recalculate the value with every new render!

```javascript
const User = ({name, age, email}) => { // 1
  const initials = useMemo(() => {
    name.split(" ").map(str => str.charAt(0)); // 2
  }, [name]);
  return (
    <p>{initials}</p> // 3
  );
};
```

Component will not recalculate initials when age or email changes!

So let's put this rule in our minds whenever We're creating a React component ...

> _Anything that could be calculated from props or state, Shouldn't be calculated inside a useEffect_

We've all misused the useEffect hook to achieve things that could be easily achieved without using it and without the need of having additional renders which decrease page performance.

There's only one case in which you have to use useEffect, If you want to do something when component mounts (displayed for the first time), this thing is external (API fetch, subscribing to event, Applying something to a DOM element), Simply it's not depending on state or props ... So it'll be something like this

```javascript
useEffect(() => {
    const fetchedPosts = fetch('....');
}, [])
```

## Conclusion

- useEffect should be your last choice
- useEffect runs **after rendering** your component, So if it makes any change to state, it'll cause additional renders
- Anything that could be calculated from props or state, shouldn't be calculated inside a useEffect
- You can use useMemo for expensive calculations
- You can use useEffect only if you want to do something external _(Ex: API fetch)_ when component mounts (First render only)


Thank u!