React async函数内useState赋值后取值undefined问题
问题成因
- 违反React Hook的核心调用规则:
useState仅允许在React函数组件顶层、自定义Hook顶层调用,你将useState写在普通异步函数FetchPost内部,Hook无法绑定组件的状态实例,状态更新逻辑从根源上失效。 - 异步逻辑时序错误:
setData触发的状态更新是React异步批处理的,而你写的FetchPost是async函数,执行到return语句时,状态更新还未完成,返回的Data始终是初始值null,永远拿不到请求完成后的新值。 - 状态无法持久化:每次
BlogMain组件渲染都会重新调用FetchPost,每次调用都会生成一套完全独立的临时state,既不会在多次渲染间保留状态,更新后也不会触发组件重渲染来读取新值。
解决方案
按照React规范改造逻辑,推荐封装为自定义Hook复用逻辑:
- 自定义Hook必须以
use开头命名,且Hook本身不能是async函数,请求逻辑放在useEffect内部执行,保证仅在组件挂载时发起一次请求。 - 组件顶层调用自定义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
相关产品推荐
相关产品推荐

