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

React+Mobx异步数据获取后组件不渲染问题求助

React + Mobx 数据获取后组件不渲染问题排查

你遇到的核心问题是PostsProvider传递给Context的value是一个静态对象:初始时你把postsStore.posts的当前值赋值给了value里的posts属性,当store里的posts更新时,这个value对象并不会同步变化——因为它只是保存了旧数组的引用,导致组件从Context拿到的始终是旧数据,即便用了observer也无法触发重新渲染。

解决方案1:直接传递整个Store实例到Context(推荐)

这是Mobx结合React开发的常规做法,observer会自动追踪Store中observable属性的访问,无需额外处理。

修改PostsProvider:

export const PostsProvider = ({ children }: React.PropsWithChildren) => {
    return (
        <PostsContext.Provider value={postsStore}>
            {children}
        </PostsContext.Provider>
    );
};

调整组件中的使用方式:

const List = observer(() => {
    const store = usePostsContext();
    React.useEffect(() => {
        store.fetchData();
    }, [store]);

    return (
        <ul>
            {store.posts.map((post) => (
                <li key={post.id}>{post.title}</li>
            ))}
        </ul>
    );
});

解决方案2:让Context的value响应Store变化(不推荐,冗余)

如果坚持要解构传递属性,可以通过Mobx的autorun监听Store变化,同步更新Context的value:

import { autorun } from "mobx";

export const PostsProvider = ({ children }: React.PropsWithChildren) => {
    const [contextValue, setContextValue] = React.useState({
        error: postsStore.error,
        fetchData: postsStore.fetchData,
        posts: postsStore.posts,
    });

    React.useEffect(() => {
        // 监听Store变化,同步更新Context value
        const disposer = autorun(() => {
            setContextValue({
                error: postsStore.error,
                fetchData: postsStore.fetchData,
                posts: postsStore.posts,
            });
        });
        return disposer; // 组件卸载时清理监听
    }, []);

    return (
        <PostsContext.Provider value={contextValue}>
            {children}
        </PostsContext.Provider>
    );
};

方案1更简洁高效,直接传递Store实例能让observer精准追踪状态变化,避免不必要的中间层逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:53:16