尝试从 TypeScript/React 中的提供程序访问上下文时获取"未定义"值



我是TypeScript和React Hooks的新手。所以我试着用一个简单的待办事项应用程序来学习,请原谅我:

我一直在尝试使用useContext创建一个全局状态和useState钩子。当我使用useState时,我设置了一些默认值,然而,当我试图通过提供程序访问它时,我得到一个未定义的价值。

这是我对上下文和提供者组件的实现:

import React, { createContext, PropsWithChildren, useState } from "react";
export interface AppContextType {
todos: TodoType[];
addTodo: (todo: TodoType) => void;
}
export interface TodoType {
todo: string;
}
export const AppContext = createContext<AppContextType>({} as AppContextType);
export const AppContextProvider: React.FC<PropsWithChildren> = ({ children }) => {
const [todos, setTodos] = useState<TodoType[]>([
{ todo: "Learn React" },
{ todo: "Create Todo app" },
{ todo: "Learn TypeScript" },
]);
const addTodo = (todo: TodoType) => {
setTodos([...todos, todo]);
}
return (
<AppContext.Provider value={{ todos, addTodo }}>
{children}
</AppContext.Provider>
);
}

下面是我的主App.tsx代码:

import React, { useContext } from "react";
import TodoForm from "./components/TodoForm";
import {
AppContext,
AppContextProvider,
TodoType,
} from "./context/AppContext";
function App() {
const { todos, addTodo } = useContext(AppContext);
console.log(todos); // Returns undefined.
return (
<AppContextProvider>
<ul>
{todos.map((t: TodoType) => {
return <li key={t.todo}>{t.todo}</li>
})}
</ul>
<TodoForm />
</AppContextProvider>
);
}
export default App;

我忽略了什么吗?任何帮助都很感激,谢谢!

编辑:多亏了@Erfan的回答,通过删除访问这些值的代码,并将该代码放入子组件中,这个问题得到了解决。

更新App.tsx代码:

import TodoForm from "./components/TodoForm";
import TodoList from "./components/TodoList";
import { AppContextProvider } from "./context/AppContext";
function App() {
return (
<AppContextProvider>
<TodoList />
<TodoForm />
</AppContextProvider>
);
}
export default App;

和新的TodoList组件:

import React, { useContext } from "react";
import {
AppContext,
TodoType,
} from "../context/AppContext";

const TodoList = () => {
const { todos, addTodo } = useContext(AppContext);
console.log(todos); // This is ok!
return (
<ul>
{todos.map((t: TodoType) => {
return <li key={t.todo}>{t.todo}</li>
})}
</ul>
)
}
export default TodoList;

您正在使用AppContextProvider在同一个组件中使用AppContext值。

为了使用这些值,您需要至少从比当前组件高一级的位置包装元素。

在您的例子中,您可以创建一个List组件,并在其中使用上下文值。
const List = ()=>{
const { todos, addTodo } = useContext(AppContext);
console.log(todos); // Returns undefined.
return (<ul>
{todos.map((t: TodoType) => {
return <li key={t.todo}>{t.todo}</li>
})}
</ul>)
}

应用程序:

function App() {

return (
<AppContextProvider>
<List/>
<TodoForm />
</AppContextProvider>
);}