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

如何使用React的createContext全局共享API获取的数据?

问题分析与解决方案

你的代码核心问题在于上下文类型与实际共享的数据结构不匹配,同时缺少明确的类型注解和正确的上下文使用流程,以下是分步修正方案:


1. 修正上下文类型定义(DataContext.ts)

你原本定义的PostContextType是单个帖子的结构,但实际需要共享的是「加载状态 + 帖子数组」的组合,重新定义类型并设置合理初始值:

// DataContext.ts
// 先定义单个帖子的类型
type Post = {
  userId: number;
  id: number;
  title: string;
  body: string;
};

// 定义上下文要共享的数据结构
type PostContextType = {
  loaded: boolean;
  posts: Post[] | null;
};

// 初始值必须严格匹配类型定义
const PostContext = createContext<PostContextType>({
  loaded: false,
  posts: null,
});

export default PostContext;

2. 调整DataProvider的value传递(DataProvider.tsx)

让Provider传递的value与上下文类型一致,改用对象形式提升可读性:

// DataProvider.tsx
import PostContext from './DataContext';
import { useFetch } from './useFetch';

type PostProviderProps = {
  children: React.ReactNode;
};

export default function DataProvider({ children }: PostProviderProps) {
  const [loaded, posts] = useFetch(`https://jsonplaceholder.typicode.com/posts`);
  return (
    <PostContext.Provider value={{ loaded, posts }}>
      {children}
    </PostContext.Provider>
  );
}

3. 完善useFetch的类型与逻辑(useFetch.ts)

添加泛型支持和明确的返回类型,同时优化async/await的写法(避免混合.then):

// useFetch.ts
import { useState, useEffect } from 'react';
import axios from 'axios';

// 泛型支持不同接口返回的数据类型
export const useFetch = <T>(url: string): [boolean, T | null] => {
  const [fetchedData, setFetchedData] = useState<T | null>(null);
  const [loaded, setLoaded] = useState(false);

  // 将url加入依赖,确保url变化时重新发起请求
  useEffect(() => {
    getAllFetchedData();
  }, [url]);

  const getAllFetchedData = async () => {
    try {
      const response = await axios.get(url);
      setFetchedData(response.data);
      setLoaded(true);
    } catch (error) {
      console.error(`Error: ${error}`);
      // 即使请求失败,也标记为加载完成,避免一直显示加载状态
      setLoaded(true);
    }
  };

  return [loaded, fetchedData];
};

4. 在根组件包裹DataProvider

确保所有需要访问共享数据的子组件都在Provider范围内,比如在App.tsx中:

// App.tsx
import DataProvider from './DataProvider';
import PostList from './PostList';

function App() {
  return (
    <DataProvider>
      <PostList />
    </DataProvider>
  );
}

export default App;

5. 在子组件中使用共享数据

创建子组件(比如PostList.tsx),通过useContext获取并展示数据:

// PostList.tsx
import { useContext } from 'react';
import PostContext from './DataContext';

export default function PostList() {
  const { loaded, posts } = useContext(PostContext);

  if (!loaded) {
    return <div>加载中...</div>;
  }

  if (!posts) {
    return <div>加载失败,无数据</div>;
  }

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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:20:36