How useEffect works in React

React is a popular JavaScript library for building user interfaces, and the useEffect hook is an important part of React's functional components. useEffect allows developers to perform side effects in function components, similar to how lifecycle methods work in class components.

To use useEffect, you first need to import it from the react library. You can then add it to your functional component as a hook, passing a callback function that contains the code for your side effect.

Here is an example of how to use useEffect to fetch data and set it to a component's state:

import React, { useEffect, useState } from 'react'

function ExampleComponent() {
  const [data, setData] = useState(null)

  useEffect(() => {
    fetch('https://my-api.com/data')
      .then((response) => response.json())
      .then((data) => setData(data))
  }, [])

  return <div>{data ? <p>{data.message}</p> : <p>Loading data...</p>}</div>
}

In this example, the useEffect hook is used to fetch data from an API when the component is mounted. The empty array in the second argument tells React that the effect should only run once (when the component is mounted). This is useful for avoiding unnecessary network requests when the data does not change.

When to use useEffect?

You should use the useEffect hook when you want to perform side effects in your function components. Side effects are a fancy word for doing stuff outside the component.

This could include things like fetching data from an API, updating the document title based on some state changing, or setting up event listeners.

Just a note on State. It is important to note that the useEffect hook should only be used for side effects, and not for imperative code that directly modifies the component's state. For state updates, you should use the useState hook. Try not to mix these up or over use useEffect. Think of useEffect as a way of updating state, and then the comopnent 'Reacts' to the state.

For example, useEffect calls an API anytime the page reloads to get an array of data. The data from the API is passed into state. When the state changes, the component re-renders the array of data (in state) into a list. Anytime state changes, so does the component. Pretty cool!

In general, you should use the useEffect hook whenever you want to perform an action after a component renders. This will ensure that your component stays up-to-date and maintains the correct state.

Here is an example of how to use the useEffect hook to update a component's state when a prop changes:

import React, { useEffect, useState } from 'react'

function ExampleComponent(props) {
  const [data, setData] = useState(null)

  useEffect(() => {
    // Only fetch data if the value of the prop has changed
    if (props.value !== data) {
      fetch(`https://my-api.com/data/${props.value}`)
        .then((response) => response.json())
        .then((data) => setData(data))
    }
  }, [props.value]) // Only re-run the effect when props.value changes

  return <div>{data ? <p>{data.message}</p> : <p>Loading data...</p>}</div>
}

In this example, the useEffect hook is used to fetch data from an API when the value prop of the ExampleComponent changes. The [props.value] array in the second argument tells React that the effect should only run when the value prop changes. This is useful for avoiding unnecessary network requests when the data does not change.

There you have it. useEffect is awesome. However, it is important to use the useEffect hook in moderation. Overuse of the useEffect hook can lead to unnecessary re-renders and degraded performance. It is important to carefully consider when to use the useEffect hook and to use it only when necessary. By using the useEffect hook only when needed, you can ensure that your components stay efficient and maintain the correct state.