如何在组件中使用 useContext
How to use useContext inside a component
我有一个定义为 'HeaderContext' 的上下文 - 我知道它正确地获取了我的数据,因为我可以在 console.log(headerData.Menu.PageUrl) 行中看到数据。
但是我只看到当我取消注释该行并在页面加载后保存文件时,所以我怀疑问题是页面首次加载时数据不可用。 - 这是我的第一个 React 项目,所以我想我遗漏了一些关于 React 在这里做什么的基本知识。
到目前为止,这是我的代码:
function Header() {
const [headerData] = useContext(HeaderContext)
console.log("heder data");
console.log(headerData.Menu.PageUrl);
return (
<nav>
<Link to="/">Logo here</Link>
<ul>
<li><Link to={headerData.Menu.PageUrl}>Menu</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</nav>
)}export default Header;
我得到的错误是:
index.js:10 Uncaught TypeError: Cannot read properties of undefined (reading 'PageUrl')
为清楚起见,这里是 HeaderContext:
import React, { useState, createContext, useEffect } from 'react';
import API from "../../API"
export const HeaderContext = createContext();
export const HeaderProvider = (props) => {
const [headerData, setHeaderData] = useState([]);
const getHeader = async () => {
const header = await API.fetchHeader();
setHeaderData(header);
};
useEffect(() => {
getHeader();
}, []);
return (
<HeaderContext.Provider value={[headerData]}>
{props.children}
</HeaderContext.Provider >
);}
这里是 App.js 文件:
function App() {
return (
<MenuProvider>
<div className="App">
<HeaderProvider>
<Header />
</HeaderProvider>
<Routes>
<Route path="/menu" element={<Menu />} />
<Route path="/menu/:id" element={<Category />} />
<Route path="/contact" element={<Contact />} />
<Route path="/more/faqs" element={<Faqs />} />
{/*<Home />*/}
</Routes>
<Footer />
</div>
</MenuProvider>
);
}
我怀疑问题出在这里:
const getHeader = async () => {
const header = await API.fetchHeader();
setHeaderData(header);
};
您正在异步设置 headerData
,然后将其作为上下文提供程序的值传递。所以数据是稍后设置的,当 fetchHeader 完成时。基本上你首先传递一个空数组,然后在异步操作完成后,你将它设置为我猜的对象(我不确定 API returns 是什么)。
查看此内容以了解如何在 useEffect
挂钩中使用异步函数:https://devtrium.com/posts/async-functions-useeffect
初始headerData
值为空数组:
const [headerData, setHeaderData] = useState([]);
并在数组中传入上下文值:
<HeaderContext.Provider value={[headerData]}>
{props.children}
</HeaderContext.Provider>
但您正在访问 headerData
值,就好像它是一个对象一样
console.log(headerData.Menu.PageUrl);
既然你说这适用于后续渲染,它让我相信 headerData
实际上 确实是一个对象。您的邮递员回复证实了这一点。
您遇到的问题是,由于 headerData
是一个数组,因此 Menu
属性 未定义。这没问题,直到您尝试访问未定义对象的 PageUrl
属性。
修复初始 headerData
状态值也是一个对象:
const [headerData, setHeaderData] = useState({});
您可能还想将其作为对象传递给 Context 值:
<HeaderContext.Provider value={headerData}>
{props.children}
</HeaderContext.Provider>
然后 return 成功了:
const headerData = useContext(HeaderContext);
从这里开始,您只需要使用可选链接或 null-checks/guard 子句来访问可能未定义的属性。
示例:
headerData.Menu?.PageUrl
headerData.Menu && headerData.Menu.PageUrl
通常是 object 中的上下文 api return 值,但是您说的是正确获取数据。
您的错误是说您尝试访问的数据是 undefind,实际上对象 属性 目前是 undefind。
您可以这样访问数据:
<li><Link to={headerData?.Menu?.PageUrl}>Menu</Link></li>
第一个解决方案:
使用可选链接,它可以帮助您在 headerData 属性未定义或为空时忽略它们。
<li><Link to={headerData?.Menu?.PageUrl}>Menu</Link></li>
或第二个解决方案:
您可以根据应用程序的需要在上下文文件中设置 headerData 对象的初始键,如下所示:
const [headerData, setHeaderData] = useState({Menu: {PageUrl: ""}});
这两种方法都会避免您的应用程序崩溃,不用担心这不是 React 中的 hack,它只是处理此类问题的正确方法之一。
我有一个定义为 'HeaderContext' 的上下文 - 我知道它正确地获取了我的数据,因为我可以在 console.log(headerData.Menu.PageUrl) 行中看到数据。
但是我只看到当我取消注释该行并在页面加载后保存文件时,所以我怀疑问题是页面首次加载时数据不可用。 - 这是我的第一个 React 项目,所以我想我遗漏了一些关于 React 在这里做什么的基本知识。
到目前为止,这是我的代码:
function Header() {
const [headerData] = useContext(HeaderContext)
console.log("heder data");
console.log(headerData.Menu.PageUrl);
return (
<nav>
<Link to="/">Logo here</Link>
<ul>
<li><Link to={headerData.Menu.PageUrl}>Menu</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</nav>
)}export default Header;
我得到的错误是:
index.js:10 Uncaught TypeError: Cannot read properties of undefined (reading 'PageUrl')
为清楚起见,这里是 HeaderContext:
import React, { useState, createContext, useEffect } from 'react';
import API from "../../API"
export const HeaderContext = createContext();
export const HeaderProvider = (props) => {
const [headerData, setHeaderData] = useState([]);
const getHeader = async () => {
const header = await API.fetchHeader();
setHeaderData(header);
};
useEffect(() => {
getHeader();
}, []);
return (
<HeaderContext.Provider value={[headerData]}>
{props.children}
</HeaderContext.Provider >
);}
这里是 App.js 文件:
function App() {
return (
<MenuProvider>
<div className="App">
<HeaderProvider>
<Header />
</HeaderProvider>
<Routes>
<Route path="/menu" element={<Menu />} />
<Route path="/menu/:id" element={<Category />} />
<Route path="/contact" element={<Contact />} />
<Route path="/more/faqs" element={<Faqs />} />
{/*<Home />*/}
</Routes>
<Footer />
</div>
</MenuProvider>
);
}
我怀疑问题出在这里:
const getHeader = async () => {
const header = await API.fetchHeader();
setHeaderData(header);
};
您正在异步设置 headerData
,然后将其作为上下文提供程序的值传递。所以数据是稍后设置的,当 fetchHeader 完成时。基本上你首先传递一个空数组,然后在异步操作完成后,你将它设置为我猜的对象(我不确定 API returns 是什么)。
查看此内容以了解如何在 useEffect
挂钩中使用异步函数:https://devtrium.com/posts/async-functions-useeffect
初始headerData
值为空数组:
const [headerData, setHeaderData] = useState([]);
并在数组中传入上下文值:
<HeaderContext.Provider value={[headerData]}>
{props.children}
</HeaderContext.Provider>
但您正在访问 headerData
值,就好像它是一个对象一样
console.log(headerData.Menu.PageUrl);
既然你说这适用于后续渲染,它让我相信 headerData
实际上 确实是一个对象。您的邮递员回复证实了这一点。
您遇到的问题是,由于 headerData
是一个数组,因此 Menu
属性 未定义。这没问题,直到您尝试访问未定义对象的 PageUrl
属性。
修复初始 headerData
状态值也是一个对象:
const [headerData, setHeaderData] = useState({});
您可能还想将其作为对象传递给 Context 值:
<HeaderContext.Provider value={headerData}>
{props.children}
</HeaderContext.Provider>
然后 return 成功了:
const headerData = useContext(HeaderContext);
从这里开始,您只需要使用可选链接或 null-checks/guard 子句来访问可能未定义的属性。
示例:
headerData.Menu?.PageUrl
headerData.Menu && headerData.Menu.PageUrl
通常是 object 中的上下文 api return 值,但是您说的是正确获取数据。 您的错误是说您尝试访问的数据是 undefind,实际上对象 属性 目前是 undefind。 您可以这样访问数据:
<li><Link to={headerData?.Menu?.PageUrl}>Menu</Link></li>
第一个解决方案: 使用可选链接,它可以帮助您在 headerData 属性未定义或为空时忽略它们。
<li><Link to={headerData?.Menu?.PageUrl}>Menu</Link></li>
或第二个解决方案: 您可以根据应用程序的需要在上下文文件中设置 headerData 对象的初始键,如下所示:
const [headerData, setHeaderData] = useState({Menu: {PageUrl: ""}});
这两种方法都会避免您的应用程序崩溃,不用担心这不是 React 中的 hack,它只是处理此类问题的正确方法之一。