React's useEffect Hook
Tags: react, hooks, webdev, javascript
Published: 2021-01-18 04:35:25

One of the built-in hooks in React is the `useEffect` hook.  This is a function that runs upon every rendering of a component, starting from the initial rendering when the component first loads to any changes to the component's state.  This can be useful for tasks like fetching data or manipulating the DOM, amongst other things. 

*Note:  There will be references to the `useState` hook here, so if a quick review would be helpful, you can check out my [prior blog on `useState`](https://dev.to/maasak/simplify-with-usestate-1b6p).  I will also put a link at the end for The Net Ninja's tutorial video on this topic as well.*

# <center>Usage</center>

In order to begin using the `useEffect` hook, we will need to first import it from the React library into the component at the top:

```javascript
import { useState, useEffect } from 'react';
```

And now we can use this hook somewhere above the `return` statement.  Since this function won't return anything to us, we will not be storing it in a variable. 

```javascript
const SomeComponent = () => {
  useEffect(() => {
    console.log('useEffect hook just ran because this component rendered');
  });

  return (
    // Whatever this component is returning
  );
```
</br>
</br>
</br>

## <center>Avoid the Endless Render-Loop</center>

<img width="40%" style="width:40%" src="https://media.giphy.com/media/26u6dIwIphLj8h10A/giphy.gif">

**Beware of changing state inside the `useEffect` hook because we could end up in an endless render-loop.**  

Here is a step-by-step of what would happen if we include a function that changes state inside `useEffect`:

  1. Initial render of the component occurs
  2. `useEffect` is triggered
  3. State is updated
  4. Component re-renders due to change in state
  5. The re-render triggers `useEffect` again
  6. Back to #3, and so on and so forth...

We can remedy this issue by passing in a **dependency array** as a second argument to the `useEffect` hook.  

If we pass in an empty (dependency) array as a second argument to `useEffect`, this function will only run after the initial render, and it won't be triggered even if the component's state changes. 

```javascript
  useEffect(() => {
    console.log('useEffect hook ran on initial render of the component, but no more!');
  }, [] // All we're doing is adding this empty array here);
```

Now, let's say we want `useEffect` to run at the initial render and only whenever a certain value (meaning, a specific property of state) changes.  We can pass the reference to that value inside the dependency array (so there can be multiple ones), and `useEffect` will now know to watch that state, only triggering if any changes are made to that specific state value.

Here is what it could look like if we have a component with a `useEffect` hook that only gets triggered when there's any change made to its `number` state, ignoring any other state changes:

```javascript
const ExampleComponent = () => {
  // We are setting the initial state of `letter` and `number` using the useState hook
  const [letter, setLetter] = useState('A');
  const [number, setNumber] = useState(1);

  useEffect(() => {
    // We are logging this message to the console only at the first render of this component and when the `number` value changes
    console.log('useEffect only runs at initial render and when the `number` state changes/updates');
  // useEffect knows to watch for changes in the `number` value because we are passing it as a second argument here as a dependency 
  }, [number]);

  return (
    <div>
      // This button changes the `letter` state from `A` to `B`, but will not result in a trigger of useEffect
      <button onClick={() => setLetter('B')}>Will Not Trigger useEffect</button>
      // This button WILL trigger the useEffect hook because it is effecting the state change we are specifically listening for
      <button onClick={() => setNumber(number + 1)}>Will Trigger useEffect</button>
    </div>
  );
}
```

Thanks for reading, and Happy Coding! :smile:

# Helpful Links

[React's documentation on the useEffect Hook](https://reactjs.org/docs/hooks-effect.html)

[The Net Ninja's tutorial going over the useEffect Hook](https://www.youtube.com/watch?v=gv9ugDJ1ynU&list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d&index=14)

[The Net Ninja's tutorial on the useState Hook](https://www.youtube.com/watch?v=4pO-HcG2igk&list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d&index=8)