Basic Hooks in React - useEffect()
Tags: react, javascript, webdev, beginners
Published: 2021-01-12 14:18:20

This blog post continues the series about [React Hooks](https://reactjs.org/docs/hooks-reference.html ).

Here we are exploring one of basic and very important hooks in React - **useEffect()**.

## What is useEffect()?

**useEffect()** is JavaScript function, which lets you perform side-effects in *functional component*.  

Under *side-effects* we understand operations such as:
- data fetching
- subscriptions
- manually changing the DOM etc.

They are called "side-effects" because can affect other components and can’t be done during rendering.

## How and when use useEffect()

To use this hook, you need to import it first from React library like this:

```react

import {useEffect} from 'react';

```
You can use this hook without import as well like this - `React.useEffect()`, for me it's just more convenient to import and destructure first this function and then use it when need in the code.

You use it in your *functional component* same as you would use life-cycle methods `componentDidMount()` and `componentDidUpdate` in *class-based component* :

```react
// Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Perform necessary side-effects here
  });

```
For example, let's consider we are building an application which with get data from API (fetching data is a side-effect).  Our app will get a list of articles about Redux and display it.

First step is writing our component and defining state - an array of articles in our case, which we are going to fetch from API. Than we simply display it on the page:

```react
import { useState } from 'react';
 
const App = () => {

  const [data, setData] = useState(
     { articles:  [] });
 
  return (
    <ul>
      {data.articles.map(item => (
        <li key={item.objectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}
 
export default App;
```

Second step is to use `useEffect()` and fetch the needed data inside this hook:

```react
import { useState, useEffect } from 'react';
import axios from 'axios';
 
const App = () => {
  const [data, setData] = useState(
   { articles: [] });
 
  useEffect(async () => {
    const result = await axios(
      'https://hn.algolia.com/api/v1/search?query=redux',
    );
 
    setData(result.data);
  });
 
  return (
    <ul>
      {data.articles.map(item => (
        <li key={item.objectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}
 
export default App;

```
Here useEffect() will fetch the data with axios from the API and  set the data to the state of the component with the state hook's update function. The promise resolving happens with async/await.

But, if we run our app like it has written above, we are going to fall into an infinite loop. Why? Let's find out :)

## Characteristics and features  

**useEffect()** function can accept 2 parameters:

- callback function (provides logic for side-effect)
- dependencies array (provides list of dependencies of your side-effect: being props or state values.)

If *dependencies array* is omitted (like in our example above), then useEffect() will be invoked on every render. Why?

As written above, `useEffect()` behaves in *functional component* same as life-cycle methods `componentDidMount()` and `componentDidUpdate()` in *class-based component*. 

That means that effect hook runs not only when component mounted, but also when component is being updated. In our example we update the state inside the hook right after we have fetched data, which means effect hook will run again because component was updated. 

This is something we don't need, because we get our data only once the page is loaded and then we use it in app. 

In our case we need that dependencies array to avoid the above-described situation and run only once, so we can re-write our effect hook like this:
```react
useEffect(async () => {
    const result = await axios(
      'https://hn.algolia.com/api/v1/search?query=redux',
    );
 
    setData(result.data);
  }, [ ]);

```
So, to sum up about `useEffect()`dependencies array :

1. Not provided: the side-effect runs after every rendering

```react
import { useEffect } from 'react';

const MyComponent = () => {
  useEffect(() => {
    // Runs after EVERY rendering
  });  
}
```
2.An empty array []: the side-effect runs once after the initial rendering

```react
import { useEffect } from 'react';

const MyComponent = () => {
  useEffect(() => {
    // Runs ONCE after initial rendering
  }, []);
}
```
3.Has props or state values [prop1, prop2, ..., state1, state2]: the side-effect runs only when any dependancies value changes.

```react
import { useEffect } from 'react';

const MyComponent = ({ prop }) => {
  useEffect(() => {
    // Runs ONCE after initial rendering
    // and after every rendering ONLY IF `prop` changes
  }, [prop]);
}

```
You can use multiple `useEffect()` hooks in one component, each implementing its own logic. You can create customs hooks and use `useEffect()` inside it. Once you get more confidence and practice with this hook, you can do magic!

Resources used:
- https://dmitripavlutin.com/react-useeffect-explanation/
- https://reactjs.org/docs/hooks-effect.html

Thank you for reading my blog. Feel free to connect on [LinkedIn](https://www.linkedin.com/in/olenadrugalya/) or [Twitter](https://twitter.com/OlenaDrugalya) :)

<a href='https://ko-fi.com/J3J42JOOA' target='_blank'><img height='12' width=30% style='border:0px;height:12px;' src='https://cdn.ko-fi.com/cdn/kofi1.png?v=2' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>