React中如何用setState处理存在依赖关系的两个GET请求?
处理依赖式请求的最优方案
你遇到的核心问题是依赖异步状态更新的请求时机错误:useState的更新是异步批量处理的,第一个请求里调用setPageId后,state不会立刻更新,所以后续调用getTemplates时拿到的还是初始的null。下面是两种最可靠的解决思路:
方案一:直接传递pageId,绕过state异步更新(推荐)
既然第一个请求已经拿到了pageId,直接把这个值作为参数传给getTemplates,完全避开state的异步问题,这是最直接高效的方式。
修改后的代码:
const [loadedSharePages, setLoadedSharePages] = useState(null); const [loadedTemplates, setLoadedTemplates] = useState([]); // 若其他业务逻辑不需要用到pageId,这个state甚至可以删掉 const [pageId, setPageId] = useState(null); const url = useParams().url; const getCustomUrl = async () => { try { const res = await axios({ method: "GET", url: `http://localhost:8080/api/pages/DT/${url}`, headers: { Authorization: "Bearer " + localStorage.getItem("token"), }, }); console.log("Respond from the request getCusomUrl-->", res); setLoadedSharePages(res.data.page); setPageId(res.data.page.id); // 直接把请求返回的pageId传给getTemplates,不用等state更新 await getTemplates(res.data.page.id); } catch (err) { console.log(err); } }; // 修改getTemplates,接受pageId参数 const getTemplates = async (targetPageId) => { try { const res = await axios({ method: "GET", url: `http://localhost:8080/api/RE/template/${targetPageId}`, headers: { "Content-Type": "multipart/form-data", Authorization: "Bearer " + localStorage.getItem("token"), }, }); console.log("Respond from the request -->", res); setLoadedTemplates(res.data.templates); console.log("Res.data.templates -->", res.data.templates); } catch (err) { console.log(err); } }; useEffect(() => { getCustomUrl(); }, [url]); // 依赖url参数,当url变化时重新发起请求
方案二:用useEffect监听pageId变化(适合依赖state的场景)
如果你的业务逻辑确实需要把pageId存在state中(比如其他组件或逻辑要用到),可以用useEffect监听pageId的变化,当它不为null时再发起第二个请求。
修改后的代码:
const [loadedSharePages, setLoadedSharePages] = useState(null); const [loadedTemplates, setLoadedTemplates] = useState([]); const [pageId, setPageId] = useState(null); const url = useParams().url; const getCustomUrl = async () => { try { const res = await axios({ method: "GET", url: `http://localhost:8080/api/pages/DT/${url}`, headers: { Authorization: "Bearer " + localStorage.getItem("token"), }, }); setLoadedSharePages(res.data.page); setPageId(res.data.page.id); } catch (err) { console.log(err); } }; const getTemplates = async () => { // 先判断pageId是否有效,避免发起无效请求 if (!pageId) return; try { const res = await axios({ method: "GET", url: `http://localhost:8080/api/RE/template/${pageId}`, headers: { "Content-Type": "multipart/form-data", Authorization: "Bearer " + localStorage.getItem("token"), }, }); setLoadedTemplates(res.data.templates); } catch (err) { console.log(err); } }; // 第一个副作用:发起页面信息请求 useEffect(() => { getCustomUrl(); }, [url]); // 第二个副作用:监听pageId变化,发起模板请求 useEffect(() => { getTemplates(); }, [pageId]); // pageId更新时触发
为什么你之前的方法没生效?
- Promise链式调用:
getCustomUrl()执行完成后,setPageId的异步更新还未完成,此时pageId依然是null,所以getTemplates()拿到的还是旧值。 - setTimeout:完全不可靠,请求耗时不确定,无法保证在指定时间内state完成更新。
- useEffect加pageId依赖无效:大概率是没处理
pageId为null的情况,导致第一次触发时发起了无效请求。
内容的提问来源于stack exchange,提问作者yuroni
相关产品推荐
相关产品推荐

