You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React自定义fetch post Hook请求成功后无法将数据存入state问题

问题原因及修复方案

核心问题原因

  • React的状态更新是异步批量执行的,调用setRespuestaAPI之后,当前渲染闭包内的respuestaAPI仍然是更新前的旧值,需要等到组件触发重渲染之后才能拿到最新状态,所以你在set之后立刻打印会拿到空的初始值。
  • 表单侧调用fetchData时没有加await,请求还没执行完成就打印respuestaAPI,此时状态还没更新,自然为空。
  • 原有判断逻辑if ("status")存在语法错误,非空字符串的布尔值永远为true,无论接口是否请求成功都会走成功分支。
  • useCallback依赖中直接写JSON.stringify(body)会导致不必要的函数重新生成,对象属性顺序变化就会触发依赖更新。

修复方案

自定义Hook修复

调整参数结构,将请求body改为fetchData的入参,同时增加错误捕获、直接返回请求结果方便调用方使用:

import { useState, useCallback } from 'react';

export default function useFetchPost(path) {
    const [respuestaAPI, setRespuestaAPI] = useState({});
    const [status, setStatus] = useState(false);
    const [pending, setPending] = useState(false);

    const fetchData = useCallback(async (body) => {
        const payload = {
            method: "POST",
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(body)
        };
        setPending(true);
        try {
            const response = await fetch("http://localhost:8080" + path, payload);
            const datos = await response.json();
            setRespuestaAPI(datos);
            const reqStatus = response.ok;
            setStatus(reqStatus);
            setPending(false);
            // 直接返回请求结果和状态,不用等状态更新就能拿到数据
            return { datos, status: reqStatus };
        } catch (err) {
            setStatus(false);
            setPending(false);
            throw err;
        }
    }, [path])

    return { respuestaAPI, fetchData, pending, status }
}

调用侧代码修复

将handleClick改为异步函数,加await等待请求完成,直接拿返回的结果做逻辑判断:

// 调用Hook时仅传入接口路径
const { respuestaAPI, fetchData, pending } = useFetchPost("/usuario");

const handleClick = async () => {
    const usuario = {
        nombre: values.username,
        apellido: values.lastname,
        email: values.email,
        password: values.password,
        ciudad: usuarioEncontrado.ciudad,
        token: ""
    }
    try {
        // 等待请求完成,拿到返回结果
        const { datos, status } = await fetchData(usuario);
        if (status) {
            // 存储接口返回的完整用户数据(包含生成的token)
            window.localStorage.setItem("usuario", JSON.stringify(datos));
            handleLogin(true);
        } else {
            setErrors({
                ...errors,
                usuarioNoCreado: "Lamentablemente no ha podido registrarse. Por favor intente más tarde"
            })
        }
    } catch (err) {
        setErrors({
            ...errors,
            usuarioNoCreado: "网络请求异常,请稍后重试"
        })
    }
}

// 其他需要使用接口返回数据的场景直接取respuestaAPI即可,状态更新后会自动触发重渲染

补充说明

如果需要在请求完成后,在组件其他位置使用返回的数据,直接读取respuestaAPI即可,请求成功后状态自动更新,所有依赖该状态的组件都会同步拿到最新值。

内容的提问来源于stack exchange,提问作者maropra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 00:45:09