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()都会被执行一次,和你预期的执行时机完全不符。
修复方式
- 修正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; - 如果你不需要开发态的严格校验,可以在项目入口文件(通常是
index.js)中移除包裹根组件的<React.StrictMode>标签,开发环境初始化时就不会出现双调用。但更推荐保留严格模式,它能帮你提前排查代码隐患,双调用本身不会对生产环境的逻辑产生任何影响。
补充纠正:你预期「点击按钮时会触发初始化函数打印」的认知是错误的。state初始化逻辑仅在组件首次挂载时执行,组件挂载完成后触发的更新重渲染不会重新执行state初始化逻辑,正常情况下点击按钮不会触发
display函数执行。
内容的提问来源于stack exchange,提问作者Prabhdeep Singh
相关产品推荐
相关产品推荐

