React使用useEffect请求数据后setState不生效、加载器卡住问题
问题根因
- useState更新为异步批量执行,调用
setData后立刻读取data,拿到的是当前渲染周期的旧值,因此会输出undefined,不代表赋值失败,你可以直接打印接口返回的rspnse验证返回结果是否正常。 - 加载器逻辑错误:
fetchData是异步函数,useEffect中调用fetchData后不会等待请求返回,会立刻执行setLoader(false),此时接口请求还未完成,data仍然是初始的undefined,你的渲染判断逻辑是loader || typeof data === "undefined",此时loader为false但data为undefined,因此会一直显示加载器,出现卡住的现象。
修复方案
- 将加载器关闭逻辑移到异步请求完成后执行,同时增加错误捕获避免请求失败后加载器一直旋转
- 若要验证data更新结果,可以新增useEffect监听data变化后打印,或直接打印接口返回的rspnse
- 渲染读取data属性时增加可选链判断,避免数据结构异常时报错
修复后的完整代码:
import React, { useState, useEffect } from "react"; import * as S from "./Service.js"; import { Loader } from "./Loader.js"; function NeedHelp() { const [loader, setLoader] = useState(true); const [data, setData] = useState(); async function fetchData() { try { setLoader(true); const rspnse = await S.getData(); setData(rspnse); // 这里直接打印rspnse就能拿到正确返回值 console.log("接口返回数据 :\n", rspnse); } catch (err) { console.error("请求失败", err); } finally { // 请求无论成功失败都关闭加载器 setLoader(false); } } useEffect(() => { fetchData(); }, []); // 监听data变化,更新后打印最新的state值 useEffect(() => { console.log("data更新后的值:\n", data); }, [data]) return ( <div className=" pt-3 p-1 mx-1 w-full"> {loader || typeof data === "undefined" ? ( <Loader /> ) : ( data && ( <div> <div id="first row" className="border p-2"> <span className="px-4 px-4 flex border"> <input className="w-1/5 text-xs rounded py-1 px-1.5 placeholder-gray placeholder-opacity-75 focus:ring-0.5 focus:ring-blue focus:border-blue" type="text" placeholder="Filter..." ></input> <div id="search_clear" className=" mx-1"> <button onClick="" className="text-white rounded px-1.5 py-1 mx-0.5 bg-blue transition duration-500 ease-in-out transform hover:translate-x-1 hover:scale-110 hover:bg-blue hover:shadow-lg" > Clear </button> </div> <div className="self-center"> <p className="text-sm text-bgray ml-5"> {/* 加可选链避免结构异常报错 */} Number of View: {data?.data?.length ?? 0} </p> </div> </span> </div> <div id="table"> <table className="table_auto w-full"> <thead> <tr className=""> <th className=" "> Name</th> <th className=" "> ID</th> <td className=" "></td> <td className=" "></td> </tr> </thead> <tbody className="border"> <tr> <td className="border">1</td> <td className="border">2</td> <td className="border">3</td> <td className="border">4</td> </tr> </tbody> </table> </div> </div> ) )} </div> ); } export default NeedHelp;
内容的提问来源于stack exchange,提问作者lhumanl
相关产品推荐
相关产品推荐

