React.useContext() 不断返回未定义?

Posted

技术标签:

【中文标题】React.useContext() 不断返回未定义?【英文标题】:React.useContext() keeps returning undefined? 【发布时间】:2020-09-01 09:31:36 【问题描述】:

我正在使用 Next.js 和 React,使用 react hooks + context 来管理状态。但是,我遇到了这个问题,React.useContext() 返回 undefined 即使我传递了我的上下文对象(或者我认为,无论如何)。我错过了一些非常明显的东西吗?发生了什么事?

我在一个名为 CartContext 的 const 中创建了上下文,然后在我的提供程序组件中,我创建了值对象并将其作为 prop 传递给 CartContext.Provider(见下文,_app.js)。我通过添加 <h1> 元素来确保上下文提供程序包装了我的组件,以确保。

问题似乎出现在index.js。我从./_app.js 导入了 CartContext,然后将它作为参数传递给useContext(),这应该是我应该做的,但它一直抛出这个错误:

“TypeError:无法解构‘react__WEBPACK_IMPORTED_MODULE_0___default.a.useContext(...)’的属性‘firstSample’,因为它是未定义的”

我收集到的信息告诉我 useContext() 正在返回未定义。

_app.js(包装所有页面)

import React from 'react'
import '../styles/global.css';
import theme from '../components/customTheme';
import  ThemeProvider  from '@material-ui/core/styles';

const MyApp = props => 
  const  Component, pageProps, store  = props

  return (
    <ContextProvider>
      <ThemeProvider theme=theme>
        <Component ...pageProps />
      </ThemeProvider>
    </ContextProvider>
  )


// Context 

export const CartContext = React.createContext()

function ContextProvider( children ) 
  const value = 
    firstSample: "Test",
    exampleFunction: () => alert("Hello World"),
  

  return (
    <CartContext.Provider value=value>
      <h1>The provider works</h1>
      children
    </CartContext.Provider>
  )



export default MyApp;

index.js

import Nav from '../components/nav';
import Footer from '../components/footer';
import Product from '../components/product';
import  makeStyles  from '@material-ui/core/styles';
import CartContext from './_app';
import 
    Typography,
    Button
 from '@material-ui/core';

const useStyles = makeStyles(
    body: 
        margin: '13vh 0 3vh',
        backgroundColor: ' white',
        textAlign: 'left'
    ,
    earnWrapper: 
        display: 'block',
        textAlign: 'left',
        backgroundColor: 'white',
        width: 'calc(100% - 4vh)',
        margin: '5% 2vh 12%',
        borderRadius: '25px',
        transition: '0.3s',
        boxShadow: '0px 5px 20px #dedede'
    ,
    earnContent: 
        padding: '7%',
        textAlign: 'left',
        display: 'inline-block'
    ,
    earntCaption: 
        color: 'grey',
    ,
    earntAmount: 
        margin: '0.5vh  0 1.5vh'
    ,
    withdraw: 
        width: '130px',
        height: '40px'
    ,
    shareInfo: 
        margin: '5%  2vh',
        textAlign: 'left'
    , 
    products: 
        textAlign: 'center ',
        width: '100%'
    
);

export default function Home(props) 
    const styles = useStyles();

    // Grab data from parent context
   const  firstSample  = React.useContext(
       CartContext
   )

    return (
        <div>

            <DefaultHead
            title="Oorigin | Home"
            />

            <Nav isLoggedIn=true />

            <div className=styles.body>
                <div className=styles.earnWrapper>
                    <div className=styles.earnContent>
                        <Typography className=styles.earntCaption variant="caption">You've earned</Typography>
                        <Typography className=styles.earntAmount variant="h4">S$18.50</Typography>
                        <Button className=styles.withdraw disableElevation variant="contained" color="primary">Withdraw</Button>
                    </div>
                </div>
                <div className=styles.shareInfo>
                    <Typography><b>Shop, Share, Earn</b></Typography>
                    <Typography><br/>Shop products you like, share products you love, and earn up to 10% commission on every qualifying sale you refer</Typography>
                </div>
                <div className=styles.products>
                    <Product
                    imgURL="../TestItem1.svg"
                    imgAlt="Test Product"
                    title="Disinfecting Air Purifying Solution"
                    price=(22.80).toFixed(2)
                    link="/products/staticProduct"
                    />
                    <Product
                    imgURL="../TestItem2.svg"
                    imgAlt="Test Product"
                    title="Disinfecting Air Purifying Solution"
                    price=(22.80).toFixed(2)
                    />
                    <Product
                    imgURL="../TestItem3.svg"
                    imgAlt="Test Product"
                    title="Disinfecting Air Purifying Solution"
                    price=(22.80).toFixed(2)
                    />
                    <Product
                    imgURL="../TestItem4.svg"
                    imgAlt="Test Product"
                    title="Disinfecting Air Purifying Solution"
                    price=(22.80).toFixed(2)
                    />
                </div>
            </div>

            <Footer/>

            <h1>firstSample</h1>
        </div>
    );

【问题讨论】:

【参考方案1】:

您的代码有一些问题,我不明白为什么您的createContext 与组件&lt;MyApp /&gt; 保持一致。

问题:

MyApp组件中你正在做export default MyAppexport CartContext,我相信这是不可能的。 您的createContext 没有defaultValue,也许这就是返回undefined 的原因。请参阅documentation 中的示例

我相信通过进行这些更改,您的代码应该可以工作,或者至少您可以解决您的问题。

使用codesandbox会更容易。

【讨论】:

原来我刚刚导入了 CartContext 错误(见我的回答)。我可以同时拥有两个导出,如果它不是默认导出,则只需要使用大括号导入即可。至于createContext,我看过文档,defaultValue 是可选的。该程序现在可以运行了,我还没有通过任何defaultValue【参考方案2】:

好吧,这是一个非常简单的错误,我将CartContext 导入index.jsimport cartContex from _app.js,它应该带有花括号,因为它不是默认导出。所以更正的(功能)代码很简单:import cartContext from _app.js

【讨论】:

以上是关于React.useContext() 不断返回未定义?的主要内容,如果未能解决你的问题,请参考以下文章

React - useContext 返回值后加载组件

React:useContext,如何从外部组件中检索它?

React.useContext 没有更新

React.useContext 显示为未定义

在使用数据库数据更新上下文后,React 'useContext' 钩子不会重新渲染

React useContext 值没有从提供者传递过来?