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

React useState初始化函数重复执行 日志打印两次问题排查

重复打印的核心原因

两个因素共同导致了初始加载时打印两次日志:

  • React 18 开发态严格模式的双调用校验机制
    React 18 之后,开发环境下只要组件被<StrictMode>包裹(Create React App等脚手架的默认配置),React会刻意重复执行一次组件初始化流程,包括state初始化逻辑、渲染函数、effect挂载/清理逻辑,目的是提前捕获代码中不符合纯函数要求的隐式副作用。这个重复调用只在开发环境存在,生产环境打包后会自动移除。
  • useState传参写法错误
    你当前的代码写的是useState(display()),这行代码的执行逻辑是:组件每次渲染时,都会先立刻执行display()拿到返回值,再把返回值传入useState。你并没有把display函数本身作为初始化回调传给useState,只是传入了它的执行结果。
    按照useState的设计,只有直接传入函数引用(即useState(display))时,传入的函数才会被React接管,仅在state初始化阶段执行。你现在的写法哪怕关闭严格模式,后续每次组件重渲染(比如点击按钮触发count更新后),display()都会被执行一次,和你预期的执行时机完全不符。
修复方式
  1. 修正useState的传参,直接传入函数引用,不要手动加括号调用,同时建议把state更新写法改成函数式更新,避免闭包导致的state值陈旧问题:
    import React, {useState} from 'react'
    import logo from './logo.svg';
    import './App.css';
    import {Alert, Button} from 'react-bootstrap'
    
    function App() {
      const display = () => {console.log("abra-ca-dabra"); return 0}
      // 修正:直接传函数引用作为初始化参数
      const[count, setCount] = useState(display)
    
      const increment = () => setCount(prev => prev + 1)
      const decrement = () => setCount(prev => prev - 1)
    
      return (
        <div className="App">
          <Button variant="info" onClick={increment}>+</Button>
          <Alert>{count}</Alert>
          <Button variant='warning' onClick={decrement}>-</Button>
        </div>
      );
    }
    
    export default App;
    
  2. 如果你不需要开发态的严格校验,可以在项目入口文件(通常是index.js)中移除包裹根组件的<React.StrictMode>标签,开发环境初始化时就不会出现双调用。但更推荐保留严格模式,它能帮你提前排查代码隐患,双调用本身不会对生产环境的逻辑产生任何影响。

补充纠正:你预期「点击按钮时会触发初始化函数打印」的认知是错误的。state初始化逻辑仅在组件首次挂载时执行,组件挂载完成后触发的更新重渲染不会重新执行state初始化逻辑,正常情况下点击按钮不会触发display函数执行。

内容的提问来源于stack exchange,提问作者Prabhdeep Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:36:15