React异步函数刷新页面后返回undefined,编译后恢复正常
问题原因拆解
1. console.log(data) 显示undefined
React的setState是异步批量更新机制,调用setData(responseData)后,组件不会立刻重新渲染,当前函数作用域里的data还是初始的undefined(闭包保留了当前渲染周期的state值)。所以你紧接着打印的data是旧值,并非刚设置的新数据。
2. responseData 打印两次
这是React 18开发环境下Strict Mode的特性:它会自动执行两次副作用(比如useEffect内的代码),用来检测组件是否存在副作用泄漏、非幂等操作等潜在问题。刷新页面时触发完整的组件初始化流程,所以会触发两次;而webpack热重载时是组件增量更新,Strict Mode的重复执行逻辑未触发,因此只打印一次。生产环境下该行为会自动消失。
解决办法
针对console.log(data) undefined的问题
不要在setData后立即打印,而是通过useEffect监听data的变化,待data更新完成后再打印:
useEffect(() => { if (data) { console.log(data); } }, [data]); // 依赖data,仅当data变化时执行
或者理解异步更新特性:新的data会在组件下一次渲染时生效,之后在JSX或其他依赖data的逻辑中直接使用即可。
针对两次打印的问题
这是开发环境的调试特性,生产环境不会出现。如果觉得开发时看着烦,可以暂时关闭项目根组件的StrictMode包裹(比如index.js里的<React.StrictMode>),但不推荐长期这么做——Strict Mode能帮你提前发现很多潜在bug。如果你的副作用是幂等的(比如这个fetch请求,重复调用无不良影响),完全可以忽略该现象。
修改后的完整代码示例
import React, { useEffect, useState } from "react"; const endpointUrl = "https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1h&limit=5"; const Test = () => { const [data, setData] = useState(); useEffect(() => { const fetchApi = async () => { const response = await fetch(endpointUrl); const responseData = await response.json(); console.log(responseData); setData(responseData); }; fetchApi().catch(console.error); }, []); // 监听data变化,更新后打印 useEffect(() => { if (data) { console.log("更新后的data:", data); } }, [data]); return ( <div> <ul> {data ? data.map((item, index) => ( <li key={index}>{new Date(item[0]).toLocaleString()}</li> // 示例渲染格式化后的时间 )) : "Loading..."} </ul> </div> ); }; export default Test;
内容的提问来源于stack exchange,提问作者lucasczr
相关产品推荐
相关产品推荐

