Home > other >  useEffect called twice - useCallback has not effect
useEffect called twice - useCallback has not effect

Time:07-06

An API call is being made from useEffect() and when the application is refreshed, useEffect() is called twice and API is call is made twice.

// App.js

import { useEffect, useCallback } from "react";

function App() {
  const fetchUsers = useCallback(async () => {
    try {
      const response = await fetch(
        "https://jsonplaceholder.typicode.com/users"
      );
      const data = await response.json();
      console.log("data: ", data); // displayed two times in console.
    } catch (error) {
      console.log("Error in catch!");
    }
  }, []);

  useEffect(() => {
    fetchUsers();
  }, [fetchUsers]);
}

export default App;

how to fix this? useCallback() also has no effect in not invoking fetchUsers() function twice.

Here is the full code. CodeSandBox

using react v18

Edit: Removing <React.StrictMode> has solved the issue, but I don't want to remove it, as it is useful in warning potential issues in the application.

Is there any other solution?

CodePudding user response:

New Strict Mode Behaviors

In short, there is no "fix" as this is intentional. Do not remove Strict mode as some users are suggesting. You will see it only in development mode.

In the future, we’d like to add a feature that allows React to add and remove sections of the UI while preserving state. For example, when a user tabs away from a screen and back, React should be able to immediately show the previous screen. To do this, React would unmount and remount trees using the same component state as before.

This feature will give React apps better performance out-of-the-box, but requires components to be resilient to effects being mounted and destroyed multiple times. Most effects will work without any changes, but some effects assume they are only mounted or destroyed once.

To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.

CodePudding user response:

It's the Default behavior in react18.You can check using the below link.

techiediaries.com/react-18-useeffect

You can try this solution:

Removed strict mode of react and it works normally.

import { useEffect, useCallback } from "react";

function App() {
  const fetchUsers = useCallback(async () => {
    try {
      const response = await fetch(
        "https://jsonplaceholder.typicode.com/users"
      );
      const data = await response.json();
      console.log("data: ", data);
    } catch (error) {
      console.log("Error in catch!");
    }
  }, []);

  useEffect(() => {
    var ignore = false;
    if (!ignore) {
      ignore = true;
      fetchUsers();
    }
  }, [fetchUsers]);
}

export default App;
  • Related