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

在TypeScript/React中从Provider访问Context时获取undefined值

问题:useContext结合useState实现全局状态时获取到undefined

问题描述

作为TypeScript和React Hooks新手,我在开发简易待办应用时尝试用useContext和useState实现全局状态管理。明明给useState设置了默认值,但在Provider中访问状态时却得到undefined。

原实现代码

Context与Provider组件

// TodoContext.tsx
import { createContext, useState, ReactNode } from 'react';

interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

interface TodoContextType {
  todos: Todo[];
  addTodo: (text: string) => void;
}

// 创建Context,设置默认值占位
export const TodoContext = createContext<TodoContextType | undefined>(undefined);

export const TodoProvider = ({ children }: { children: ReactNode }) => {
  const [todos, setTodos] = useState<Todo[]>([
    { id: 1, text: '学习React Hooks', completed: false },
    { id: 2, text: '学习TypeScript', completed: false }
  ]);

  const addTodo = (text: string) => {
    setTodos(prev => [...prev, { id: Date.now(), text, completed: false }]);
  };

  return (
    <TodoContext.Provider value={{ todos, addTodo }}>
      {children}
    </TodoContext.Provider>
  );
};

原App.tsx代码

// App.tsx
import { useContext } from 'react';
import { TodoContext, TodoProvider } from './TodoContext';

function App() {
  // 在Provider的同级组件中直接调用useContext,导致获取到undefined
  const { todos } = useContext(TodoContext)!;

  return (
    <TodoProvider>
      <div className="App">
        <h1>待办列表</h1>
        <ul>
          {todos.map(todo => (
            <li key={todo.id}>{todo.text}</li>
          ))}
        </ul>
      </div>
    </TodoProvider>
  );
}

export default App;

问题原因

useContext只能在被Provider包裹的子组件中调用才能获取到正确的上下文值。原代码中App组件是TodoProvider的父级(直接渲染TodoProvider),此时调用useContext时,组件还未被TodoProvider包裹,无法获取上下文数据,返回的是创建Context时设置的默认值undefined。

解决方法

将访问Context状态的逻辑抽离到子组件中,确保该子组件被TodoProvider包裹,再在子组件内调用useContext。

修改后代码

新增TodoList子组件

// TodoList.tsx
import { useContext } from 'react';
import { TodoContext } from './TodoContext';

export const TodoList = () => {
  const { todos } = useContext(TodoContext)!;
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
};

修改后的App.tsx

// App.tsx
import { TodoProvider } from './TodoContext';
import { TodoList } from './TodoList';

function App() {
  return (
    <TodoProvider>
      <div className="App">
        <h1>待办列表</h1>
        <TodoList />
      </div>
    </TodoProvider>
  );
}

export default App;

经@Erfan提示调整后,问题成功解决,现在可以正常获取到全局状态中的todos数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:09:31