React 18 严格模式导致组件渲染两次

nei*_*eil 23 javascript development-environment reactjs react-strictmode

React 版本 18中对严格模式的更改导致我的代码渲染两次,这会导致axios abort 控制器出现错误,但我不知道如何在应用程序渲染两次后从浏览器控制台清除错误。

请注意:我正在开发一个注册/登录应用程序,即使在我成功登录后,由于axios错误, React也会将我带回登录页面

useEffect(() => {
    let isMounted = true;
    // used by axios to cancel request
    const controller = new AbortController();

    const getGoals = async () => {
        try {
            const response = await goalPrivate.get("/goals", {
                // option to cancel request
                signal: controller.signal
            })
            console.log(response?.data);
            // set goals state when component mounts
            isMounted && setGoals(response?.data);
        } catch (error) {
            console.log(error.message);
            // when refreshToken expires
            navigate("/login", { state: { from: location }, replace: true });
        }
    }

    getGoals();

    // cleanup function
    return () => {
        // don't set state if component unmounts
        isMounted = false;
        // cancel request if component unmounts
        controller.abort();
    }
    
    // eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Run Code Online (Sandbox Code Playgroud)

Dus*_*omp 20

React StrictMode 调用所有 Effects 两次,以确保它们的清理/卸载处理程序按预期工作。您可能需要相应地更改效果,即使它们具有空的依赖项列表并且通常不会在站点关闭之前卸载。

请注意,这只发生在严格+开发模式下。在生产构建中,效果只会在其依赖项发生变化时被调用一次。

有关更多上下文,请参阅https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state

  • 有关更详细的答案/sf/answers/5056676551/ (3认同)

小智 8

有同样的问题并以这种方式修复。

当 abortController 被中止时,您会跳转到 catch,因此您只需检查信号是否被中止或不执行其余代码。

useEffect(() => {
    const abortController = new AbortController();

    fetch("https://pokeapi.co/api/v2/pokemon", {
      signal: abortController.signal,
    })
      .then((res) => res.json())
      .then(console.log)
      .catch((err) => {
        if (abortController.signal.aborted) return;
        console.log(err);
        // Your navigate
      });

    return () => {
      abortController.abort();
    };
  }, []);
Run Code Online (Sandbox Code Playgroud)


nei*_*eil 0

React 18 现在Strict.Mode可以挂载、卸载和重新挂载组件,这会导致 abortController第一次卸载时发出错误。请记住,这只发生在开发模式下,即在 index.js 中应用 Strict.Mode 时。我们可以在开发模式下检查该行为。

try {
     // fetch API data
  } catch (error) {
       if (process.env.NODE_ENV === "development" && error) {
         // ignore the error
        console.log(error.message);
   } else {
     // when refreshToken expires, go back to login
    navigate("/login", { state: { from: location }, replace: true });
  }
}
Run Code Online (Sandbox Code Playgroud)