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

React async函数内useState赋值后取值undefined问题

问题成因
  • 违反React Hook的核心调用规则:useState 仅允许在React函数组件顶层、自定义Hook顶层调用,你将useState写在普通异步函数FetchPost内部,Hook无法绑定组件的状态实例,状态更新逻辑从根源上失效。
  • 异步逻辑时序错误:setData触发的状态更新是React异步批处理的,而你写的FetchPost是async函数,执行到return语句时,状态更新还未完成,返回的Data始终是初始值null,永远拿不到请求完成后的新值。
  • 状态无法持久化:每次BlogMain组件渲染都会重新调用FetchPost,每次调用都会生成一套完全独立的临时state,既不会在多次渲染间保留状态,更新后也不会触发组件重渲染来读取新值。
解决方案

按照React规范改造逻辑,推荐封装为自定义Hook复用逻辑:

  1. 自定义Hook必须以use开头命名,且Hook本身不能是async函数,请求逻辑放在useEffect内部执行,保证仅在组件挂载时发起一次请求。
  2. 组件顶层调用自定义Hook,等待状态更新触发重渲染后,再读取返回的数据做渲染。

正确实现代码如下:

自定义Hook(原FetchPost改造)

import axios from "axios";
import { useState, useEffect } from "react";

const useFetchPost = () => {
    const [data, setData] = useState(null)
    const [error, setError] = useState(null)
    const [loading, setLoading] = useState(false)

    useEffect(() => {
        const fetchRequest = async () => {
            setLoading(true)
            try {
                const response = await axios.get('https://...../api/blogs')
                // 注意axios返回的response.data才是接口响应体,你接口里的博客数组存在response.data.data字段下
                setData(response.data)   
            } catch (err) {
                setError(err);
            } finally {
                setLoading(false)
            }
        }
        fetchRequest()
    }, [])

    return {data, error, loading}  
}

export default useFetchPost

组件内调用

const BlogMain = () => {
    const {data, error, loading} = useFetchPost();

    // 初始渲染data为null,请求完成后组件自动重渲染,此时就能拿到正确的data值
    console.log("页面获取的博客数据:", data)

    if (loading) return <div>博客内容加载中...</div>
    if (error) return <div>加载失败:{error.message}</div>

    return (
        <div className="blog-list">
            {data?.data?.map(post => (
                <div key={post.id} className="blog-item">
                    {/* 这里根据Strapi返回的字段结构渲染内容即可 */}
                    <h3>{post.attributes.title}</h3>
                </div>
            ))}
        </div>
    )
}

export default BlogMain

补充说明:如果不想封装自定义Hook,也可以直接把useState、useEffect和请求逻辑直接写在BlogMain组件内部,效果完全一致,只是没法复用逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:24:33