React中setState赋值后仍返回空对象的问题求助
解决React异步更新state后立刻打印数据为空的问题
问题原因
你遇到的问题核心在于React的setState是异步操作,同时API请求本身也是异步的:
- 点击按钮时,
clickHandler同步执行props.onFetch(val)和console.log(props.data.weather) - API请求需要时间,此时
setState(data)还未执行完毕,props.data仍然是初始化的空对象,所以第一次打印为空 - 当API请求完成,
setState(data)触发App组件重新渲染,Input组件接收到更新后的props.data,此时会输出完整数据
解决方案
方案1:在Input组件中监听props.data的变化
利用useEffect监听props.data的更新,当数据变化后再执行打印或后续操作:
import "./Input.css"; import { useState, useEffect } from "react"; const Input = (props) => { const [val, setVal] = useState(""); const changeHandler = (e) => { setVal(e.target.value); }; const clickHandler = () => { props.onFetch(val); }; // 监听props.data变化,数据更新后执行操作 useEffect(() => { // 先判断数据是否存在,避免空对象报错 if (props.data?.weather) { console.log(props.data.weather); // 这里可以添加你需要用数据执行的逻辑 } }, [props.data]); // 依赖项为props.data,仅当它变化时触发 return ( <div> <input placeholder="🔎 Type in your city... " onChange={changeHandler} value={val} // 改为受控组件,保证输入值和state同步 /> <button onClick={clickHandler}>Click me</button> </div> ); }; export default Input;
方案2:让fetchLoc返回Promise,在Input中await后打印
修改App组件的fetchLoc函数,让它返回获取到的数据,然后在Input中等待异步操作完成后再打印:
// App组件中的fetchLoc函数修改 async function fetchLoc(value) { const res = await fetch( `https://api.openweathermap.org/data/2.5/weather?q=${value}&appid=${key}&units=imperial` ); const data = await res.json(); console.log(data); setState(data); return data; // 返回获取到的完整数据 }
// Input组件的clickHandler修改为异步函数 const clickHandler = async () => { const data = await props.onFetch(val); console.log(data.weather); // 此时打印的是最新获取的数据 };
额外说明
React的setState设计为异步是为了优化性能,它会批量处理state更新。所以永远不要在调用setState后立刻读取state或对应的props,必须等到组件重新渲染完成(可以通过useEffect监听变化),或者直接使用异步操作返回的结果来获取最新数据。
内容的提问来源于stack exchange,提问作者ATdontMiss
相关产品推荐
相关产品推荐

