React自定义手动触发请求Hook返回数据为undefined如何解决
问题原因
- 异步执行顺序问题:
fetchAppList是异步函数,useEffect中调用fetchData()后会立刻执行后续的console.log,此时请求还未返回,state也未触发更新,你拿到的永远是当前渲染闭包里的初始state值。 - React state更新的快照特性:每次渲染的state都是独立的快照,就算后续请求完成更新了state,也只会触发组件重新渲染,本次渲染作用域里的
data和status永远是初始值,不会跟着更新。
代码调整方案
1. 自定义Hook优化
原Hook存在三个问题:不需要暴露内部状态修改方法setStatus给外部、错误场景未更新状态、参数变化时请求配置不会同步更新,修改后代码如下:
import React, { useState, useMemo, useCallback } from "react"; import { AppListResponse } from "../../typings/AppListResponse"; const useFetchAppList = ( userId: string, authToken: string ): [() => Promise<void>, string, AppListResponse | null | undefined] => { const [status, setStatus] = useState<string>("idle"); const [responseData, setData] = useState<AppListResponse | null>(); // 参数变化时自动更新请求配置 const options = useMemo(() => ({ method: "GET", headers: { CustomAuthToken: authToken, UserID: userId, Accept: "application/json", "Content-Type": "application/json" } }), [userId, authToken]); // 用useCallback稳定函数引用,避免不必要的重渲染 const fetchAppList = useCallback(async (): Promise<void> => { setStatus("fetching"); let unmounted = false; try { const response = await fetch(`https://my-endpoint.com/lets-fetch-this`, options); const json = await response.json(); if (!unmounted) { setData(json); setStatus("successful"); } } catch (error) { console.log("error", error); if (!unmounted) { setStatus("error"); } } // 组件卸载时取消state更新,避免内存泄漏警告 return () => { unmounted = true; } }, [options]); // 去掉暴露的setStatus,避免外部随意修改内部状态 return [fetchAppList, status, responseData]; }; export default useFetchAppList;
2. 组件调用逻辑调整
如果需要观测请求后的最新状态,单独添加监听data和status的副作用即可:
const [fetchAppList, status, data] = useFetchAppList(userId, authToken); // 挂载时触发请求 useEffect(() => { fetchAppList(); }, [fetchAppList]); // 监听状态变化,拿到更新后的值 useEffect(() => { console.log(data, status); }, [data, status]); // 随时触发请求示例:比如绑定到按钮点击事件 const handleRefresh = () => { fetchAppList(); };
效果验证
调整后组件挂载会自动触发请求,你也可以在任意业务场景(比如按钮点击、下拉刷新)直接调用fetchAppList触发请求,status会依次变为fetching、successful/error,data会同步更新为接口返回值。
内容的提问来源于stack exchange,提问作者erol_smsr
相关产品推荐
相关产品推荐

