React调用useState更新状态后Apollo查询仍使用旧状态如何解决?
问题根源
存在两个核心错误导致请求携带旧值:
- React的
useState返回的更新方法setStatus是异步批量执行的,调用后不会立刻修改当前作用域下的status变量值,同一个函数执行上下文里拿到的还是调用setStatus之前的旧状态值 - 按钮的
onClick绑定错误:代码中写的是onClick={handleSubmit()},相当于组件渲染时就会立即执行handleSubmit,而不是点击按钮时才触发 - 补充:你提供的GraphQL mutation语法存在错误,
updateData payload: $data)少了左括号,修复后应为updateData(payload: $data)
修复方案
方案1:直接使用常量传参(最简洁,适配当前场景)
你不需要依赖state的值来传参,直接把要更新的状态定义为常量,同时给state赋值和传给mutation即可:
import React,{useState} from "react"; import { gql, useMutation } from '@apollo/client'; import Button from "@material-ui/core/Button"; const UPDATE_DATA = gql` mutation updateData( $data: UpdateDataInput!){ updateData(payload: $data) }` export default function StatusPage() { const [updateData] = useMutation(UPDATE_DATA); const [status,setStatus] = useState("OLD"); const handleSubmit = async () => { // 定义目标状态常量 const targetStatus = "NEW"; setStatus(targetStatus) try { const result = await updateData({ variables: { data: { status: targetStatus // 直接用常量传参,不需要从state取 } } }); if(result.data) { console.log("SUCCESS") } } catch (e) { console.log("ERROR") } }; return ( {/* 去掉handleSubmit后面的括号,实现点击才触发逻辑 */} <Button type ="submit" onClick={handleSubmit}> Submit </Button> ); }
方案2:用useEffect监听state变化触发请求(适配逻辑复杂、必须依赖最新state的场景)
如果后续你的逻辑里status更新可能来自多个地方,必须等state更新后再发请求,可以用useEffect监听status变化:
import React,{useState, useEffect} from "react"; import { gql, useMutation } from '@apollo/client'; import Button from "@material-ui/core/Button"; const UPDATE_DATA = gql` mutation updateData( $data: UpdateDataInput!){ updateData(payload: $data) }` export default function StatusPage() { const [updateData] = useMutation(UPDATE_DATA); const [status,setStatus] = useState("OLD"); const [shouldSubmit, setShouldSubmit] = useState(false); // 监听提交标记和status变化,状态更新后再发起请求 useEffect(() => { if(shouldSubmit && status === "NEW") { const submitRequest = async () => { try { const result = await updateData({ variables: { data: { status: status } } }); if(result.data) { console.log("SUCCESS") } } catch (e) { console.log("ERROR") } finally { setShouldSubmit(false) } } submitRequest(); } }, [status, shouldSubmit, updateData]) const handleSubmit = () => { setShouldSubmit(true); setStatus("NEW"); }; return ( <Button type ="submit" onClick={handleSubmit}> Submit </Button> ); }
内容的提问来源于stack exchange,提问作者programhur
相关产品推荐
相关产品推荐

