You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React 18基础应用中useEffect触发两次问题求助

React 18.2.0 useEffect空依赖仍多次触发的排查与解决

问题背景

搭建了极简React 18.2.0应用,期望通过useEffect配合空依赖数组仅执行一次逻辑,但实际触发多次。已确认:

  • 未使用Strict Mode
  • 无触发组件重渲染的因素
  • 组件仅被渲染一次

相关代码如下:

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配置

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

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(),
  ],
};

排查方向与解决方案

1. 修复Webpack Dev Server的热重载冲突

配置中同时开启hot: true和liveReload: true,在React 18开发环境下可能导致页面双重加载,进而触发多次useEffect:

  • 修改devServer配置,关闭liveReload:
devServer: {
  port: "9500",
  static: ["./public"],
  open: true,
  hot: true,
  liveReload: false, // 禁用liveReload,仅保留HMR
},

2. 移除手动注入的脚本

index.html中手动添加了<script defer src="main.js"></script>,同时HtmlWebpackPlugin会自动注入打包后的脚本,导致脚本被加载两次:

  • 删除index.html中的该script标签,由HtmlWebpackPlugin统一管理脚本注入

3. 确认组件挂载次数

添加日志确认组件是否被重复挂载:

const App = () => {
  console.log("App component mounted"); // 新增挂载日志
  useEffect(() => {
    console.log("trigger app");
  }, []);

  return <div />;
};

如果App component mounted打印两次,说明组件确实被重复渲染,需排查webpack入口是否重复、HtmlWebpackPlugin是否存在重复配置等问题

4. 检查Babel配置兼容性

确保@babel/preset-react版本与React 18兼容,推荐使用最新版并配置自动runtime:

{
  "presets": [
    ["@babel/preset-react", { "runtime": "automatic" }],
    "@babel/preset-env"
  ]
}

内容的提问来源于stack exchange,提问作者kc drez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 18:17:02