# React useEffect Running Twice Fix

> Understand why StrictMode double-invokes useEffect in development, and how to refactor effects or add cleanup instead of disabling it

**URL:** https://sentry.io/answers/react-useeffect-running-twice/

---

## The Problem

When developing an application in React 18+, you may encounter an issue where the `useEffect` hook is being run twice on mount.

## The Solution

This occurs because since React 18, when you are in `development`, your application is being run in [StrictMode](https://react.dev/reference/react/StrictMode) by default. In Strict Mode, React will try to simulate the behavior of mounting, unmounting, and remounting a component to help developers uncover bugs during testing.

Although this behavior may seem undesirable, or wrong, it exists to help developers ensure their code properly uses the `useEffect` hook. From [this article](https://react.dev/learn/synchronizing-with-effects) from the React team, we can see the reasoning behind `useEffect` running twice:

> **This illustrates that if remounting breaks the logic of your application, this usually uncovers existing bugs**. From the user's perspective, visiting a page shouldn't be different from visiting it, clicking a link, and then pressing Back. React verifies that your components don't break this principle by remounting them once in development.

In most cases, it should be fine to leave your code as-is, since the `useEffect` will only run once in production. In the case that your application isn't functioning correctly because it runs twice, you can try the following solutions.

### Refactor `useEffect` So That It Works Correctly After Remounting

The `useEffect` hook enables you to synchronize with state or external services that live outside the React tree.

Consider the following incorrect usage of the `useEffect` hook:

```jsx
"use client";

import { useEffect } from 'react';

export default function MyComponent() {

  useEffect(() => {
    if (product.isInCart) {
      showNotification(`Added ${product.name} to the shopping cart!`);
    }
  }, [product]);

  function handleBuyClick() {
    addToCart(product);
  }

  function handleCheckoutClick() {
    addToCart(product);
    navigateTo('/checkout');
  }

  return (
    <div>
      ...
    </div>
  );
}
```

In this example, we want to show a notification when a user puts a product in the cart. In this case, two event handlers encapsulate the `addToCart` functionality. It might be tempting to consolidate the code that shows the notification in the `useEffect`; however, this effect is incorrect and will lead to issues.

Suppose that the shopping cart is persisted through page reloads. In this case, when the page is reloaded, the notification will be shown again.

To refactor this function, we should determine why the notification should be shown. In this case, the notification should be shown because the user clicked the button, and not because the component was shown to the user. In general, effects are for code that should run because the component was shown to the user.

Using this logic, we can refactor the component as follows, removing the `useEffect`:

```jsx
"use client";

export default function MyComponent() {

  function buyProduct() {
    addToCart(product);
    showNotification(`Added ${product.name} to the shopping cart!`);
  }

  function handleBuyClick() {
    buyProduct();
  }

  function handleCheckoutClick() {
    buyProduct();
    navigateTo('/checkout');
  }

  return (
    <div>
      ...
    </div>
  );
}
```

The React documentation provides an extensive [article](https://react.dev/learn/synchronizing-with-effects) on where and how to use the `useEffect` hook correctly.

### Clean Up After the `useEffect` Hook

Consider the following component:

```jsx
"use client";

import { useEffect } from 'react';

export default function MyComponent() {

  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(count + 1);
    }, 1000);
  }, [count])

  return (
    <div>
      <h1>Count: {count}</h1>
    </div>
  );
}
```

In this component, we use the `setInterval` function to update the `count` variable every second. However, after the component is unmounted, we don't clean up. This can cause memory leaks and lead to inaccurate values of `count` when remounting.

By adding a return statement to `useEffect`, we can clean up the interval, thereby ensuring that the side effect does not persist through component mounts.

```jsx
"use client";

import { useEffect } from 'react';

export default function MyComponent() {

  const [count, setCount] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(count + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, [count])

  return (
    <div>
      <h1>Count: {count}</h1>
    </div>
  );
}
```

### Disable Strict Mode

Although it is not recommended, in React 18 you can disable Strict Mode by removing the `<React.StrictMode>` tag from the return statement in your root component.

In Next.js, you can disable Strict Mode by setting the following parameter in `next.config.js`:

```js
module.exports = {
  reactStrictMode: false,
}
```

## Additional Reading

Understanding effects in React is integral to correctly using them in your applications and avoiding errors. The React documentation contains useful and deep articles about effects and their usage. You can find several of them below:

- [Removing Effect Dependencies](https://react.dev/learn/removing-effect-dependencies)
- [Separating Events From Effects](https://react.dev/learn/separating-events-from-effects)
- [Lifecycle Of Reactive Events](https://react.dev/learn/lifecycle-of-reactive-effects)
- [You Might Not Need An Effect](https://react.dev/learn/you-might-not-need-an-effect)

---

*Source: [sentry.io/answers/react-useeffect-running-twice/](https://sentry.io/answers/react-useeffect-running-twice/)*
