Flask API+React:如何将async函数获取的数据传入useState()
问题根因
你的代码无法完成状态初始化是三个逻辑错误导致的:
- 异步请求直接写在组件函数顶层,每次组件重渲染都会重复触发,且请求返回结果没有调用状态更新方法同步到
useState useState的初始值仅在组件首次挂载时生效,异步请求返回时机晚于首次渲染,直接传入异步逻辑拿不到实际返回值- Switch组件的
onChange回调第一个参数本身就是最新的开关状态,原有代码写setToggleSwitch(!toggleSwitch)会导致状态反转错误
修复代码
先从React中引入useEffect处理异步副作用,替换原有组件逻辑即可,修复后的完整代码如下:
import React, { useState, useEffect } from "react"; import { Switch } from "antd"; import "./LightSwitch.css"; async function httpGet (url){ const response = await fetch(url,{method: 'GET'}); const string = await response.text(); const json = string === "" ? {} : JSON.parse(string); return json; } const LightSwitch = (props) => { // 初始值设为false,避免受控组件值为undefined的警告 const [toggleSwitch, setToggleSwitch] = useState(false); // 新增加载状态,避免请求未返回时显示错误开关状态 const [loading, setLoading] = useState(true); // 组件挂载、灯ID变化时拉取对应灯的真实状态 useEffect(() => { const fetchLightState = async () => { try { const res = await httpGet(`http://192.168.1.124/get_light_state/id/${props.id}`); // 接口返回后同步真实状态到组件 setToggleSwitch(res.Light); } catch (err) { console.error('获取灯状态失败:', err); } finally { setLoading(false); } } fetchLightState(); }, [props.id]) const onChangeSwitch = (checked) => { // 直接使用回调返回的最新状态更新,无需手动取反 setToggleSwitch(checked); if (checked) { console.log(props.name + ' on'); httpGet('http://192.168.1.124/turn_on/id/' + props.id); }else{ console.log(props.name + ' off'); httpGet('http://192.168.1.124/turn_off/id/'+ props.id); } }; return ( <div> <Switch checked={toggleSwitch} loading={loading} onChange={onChangeSwitch}></Switch> </div> ); }; export default LightSwitch;
关键修改说明
- 异步请求统一放到
useEffect中执行,避免组件重渲染时重复触发接口调用,依赖项配置props.id后,切换不同灯的ID时会自动拉取新灯的状态 - 接口请求成功拿到返回值后,主动调用
setToggleSwitch同步真实灯状态,这是原有代码缺失的核心逻辑 - 新增
loading状态,接口请求过程中开关显示加载态,避免用户看到和实际灯状态不符的默认值 - 修正开关变更逻辑,直接使用
onChange回调传入的checked参数更新状态,解决原有逻辑状态反转的bug
内容的提问来源于stack exchange,提问作者Maciej_Solowiej
相关产品推荐
相关产品推荐

