基本 React 应用程序触发 useEffect 两次

问题描述 投票:0回答:1

我四处搜寻,所有类似的帖子要么不适用,要么没有效果。我有一个非常简化的 React 应用程序(v18.2.0),我想在我的应用程序中使用 useEffect 进行渲染时执行一些 API 调用和其他逻辑。我的理解是,当提供空数组作为参数时,这只应该触发一次。

index.js:

import React from "react";
import App from "./src/App";

import { createRoot } from "react-dom/client";
const container = document.getElementById("root");
const root = createRoot(container);
root.render(<App />);

App.js:

import React, { useEffect } from "react";

const App = () => {
  useEffect(() => {
    console.log("trigger app");
  }, []);

  return <div />;
};

export default App;

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My App</title>
    <script defer src="main.js"></script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

webpack 配置:

module.exports = {
  mode: "development",
  entry: "./index.js",
  output: {
    path: path.resolve(__dirname, "public"),
    filename: "main.js",
  },
  target: ["web", "es5"],
  stats: { children: true },
  devServer: {
    port: "9500",
    static: ["./public"],
    open: true,
    hot: true,
    liveReload: true,
  },
  devtool: "inline-source-map",
  resolve: {
    extensions: [".js", ".jsx", ".json"],
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: "babel-loader",
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./public/index.html",
    }),
    new CleanWebpackPlugin(),
  ],
};

查看这篇文章,我已经验证我没有使用严格模式,似乎没有任何东西触发重新渲染,并且该组件没有被多次使用。

reactjs react-hooks webpack-dev-server
1个回答
0
投票

UseEffect 挂钩始终至少执行两次。即使您使用空依赖数组

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

第一次在组件挂载到 DOM 之前执行,第二次在组件挂载到 DOM 之后执行。

如果您想克服这个问题,并且只运行一次

useEffect
,请应用自定义挂钩来检测组件是否已安装。

通常,人们通过引用或使用

useState()

来应用此自定义钩子

创建非常简单:

使用状态:


或者如果你愿意,使用参考文献:


然后您可以在任何想要检测该组件是否已安装的组件中使用它:

import useIsMounted from '@lib/useIsMounted'
const App = ()=> {
  const isMounted = useIsMounted()
  useEffect(()=> {
    if(!isMounted) return
    // else, here, execute the following code only once, and after mount:
    console.log("you'll see me once if you disable strict mode")
  }, [])
}

如果你愿意,已经有这个钩子的 npm 包,你可以从这里下载它

$ npm i use-is-mounted-ref
然后以同样的方式:

import useIsMounted from 'use-is-mounted-ref'; // ... etc
    
© www.soinside.com 2019 - 2024. All rights reserved.