如何在组件中使用 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,它只是处理此类问题的正确方法之一。