How To Deal With Side Effects

M.Ark - Jul 10 - - Dev Community

Dealing with side effects in React is crucial to ensuring your components behave correctly and efficiently. React provides several hooks and lifecycle methods to handle side effects.

Certain components in React need to interact with things outside themselves. These things can be anything from querying data from a server to finding/changing the position of the component on the webpage or even sending some data to a server when necessary. This interaction with the outside world is called a side-effect.

Though we are already familiar with rendering code and adding event handlers, it is not enough for all uses, like when you want to connect to your server and fetch messages to show to a user.

Effects let you run some code to synchronize your component as necessary, on rendering or a reactive/state value change rather than on a particular event.

Similar to how we have the useState hook, React offers us a handy useEffect hook to use effects in our components.

Here's an overview of how to manage side effects in functional components using hooks and in class components using lifecycle methods:

Image description

If you run the code above, you do realize that the count in our wepage is inconsistenmt and it runs crazy, this implementation has a problem: _setInterval _is called every time the component renders, which will create multiple intervals and can cause performance issues.

This is where the useEffect hook swoops in to save us. We can wrap this calculation inside a useEffect hook to move it outside the rendering calculation. It accepts a callback function with all the calculations.

Image description
In the code above , we have added the useEffect function but the result from our page still runs crazy.

useEffect is a hook that lets us perform side effects in function components. Here, we use it to set up an interval that increments the counter every second.

The setInterval function runs the provided function (which increments counter) every 1000 milliseconds (1 second).

The return statement inside useEffect is a cleanup function that clears the interval when the component is unmounted to prevent memory leaks.

The dependency array

Effect Runs on Every Render: Without the dependency array, useEffect runs after every render.

This means that every time the component re-renders (which happens whenever the state or props change), a new interval is set up. This leads to multiple intervals being created, causing the counter to increment much faster than intended.

Fortunately, the second argument accepts an array of dependencies allowing the hook to re-render only when those dependencies are changed. So if you have a state variable and want to have some side-effect occur any time the state changes, you can use this hook and mention the state variable in the dependency array.

We pass an empty array in this example because we do not want the useEffect hook to run anytime other than the initial component render.
Here is how we pass an empty array.

Image description

In the code sample above, by including the dependency array,we ensure that the interval is set up only once when the component mounts and not on every render. However, it is crucial to add cleanup for the interval to prevent potential memory leaks or performance issues.

As seen now, our application counts seconds without being messy but we still have an issue with the counter updating twice every second though. That can be understood as a behavior caused by the React StrictMode.
In our code, every time the useEffect hook runs, a new setInterval is used. When the component is unmounted, setInterval is not stopped, it keeps incrementing. This unnecessary behavior can be prevented by clearing the interval when the component is unmounted and that is where the third part of our useEffect hook comes in - the cleanup function.

You can return a function from the callback in the useEffect hook, which will be executed each time before the next effect is run, and one final time when the component is unmounted. In this case, let us clean up the interval with a cleanup function.

Image description

In our code provided above:

useEffect is a hook that lets us perform side effects in function components. Here, it is used to set up an interval.

Inside useEffect, the setInterval function creates an interval that increments the counter state by 1 every 1000 milliseconds (1 second).

The const key = setInterval(...) line assigns the interval ID to a variable named key.

The return statement **inside useEffect is a cleanup function that clears the interval when the component **unmounts. This prevents memory leaks by ensuring that the interval is properly cleaned up.

The empty dependency array [] ensures that this effect runs only once, after the initial render of the component.

NB

By including the cleanup function inside the useEffect, we ensure that the interval is properly cleared when the component is unmounted, preventing potential memory leaks and ensuring efficient use of resources.

This is a summary of how useEffect hook:

useEffect(
  () => {
    // execute side effect
    return () => {
      // cleanup function on unmounting or re-running effect
    }
  },
  // optional dependency array
  [/* 0 or more entries */]
)
Enter fullscreen mode Exit fullscreen mode

Cases where useEffect does not need to be used.

  1. You do not need to use an effect if you are only calculating something based on the state during rendering. For a change in a component, due to a change in the props, you can calculate and set it during rendering.

  2. You do not need effects for events. Code that runs when a component is displayed should be in effects, the rest should be in events.

  3. You do not need an effect to reset the state based on a condition most of the time. You have learned about keys in React. Just like using a key on a list’s item, adding one to a component, based on the state on which it should be reset creates a unique version of that component for each change in the value of the state.

  4. If you are having issues with managing your state and want to use an effect to update the state of a parent or some other non-child component, consider lifting the state. As we know, in React, the state flows in one direction, generally down the DOM. So the parents know of the data before passing it to the children. If multiple children are required to make use of a single state, it should be moved up to the parent that has all of the components that need it, instead of using escape hatches like an effect.

That has brought us to the end of our learning on useEffect in React.
In case of any questions let me know and we shall go through them one by one.

Happy hacking!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .