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

jnm*_*jnm 5 javascript reactjs next.js react-hooks

我正在使用 Next.js 和 React,使用 React hooks + 上下文来管理状态。然而,我遇到了这个问题,React.useContext()即使我传递了我的上下文对象(或者我认为是这样),它也会返回未定义的问题。我是否遗漏了一些非常明显的东西?发生了什么?

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

问题似乎发生在index.js. 我已经从中导入了 CartContext,./_app.js然后将其作为参数传递给了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;
Run Code Online (Sandbox Code Playgroud)

索引.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>
    );
}
Run Code Online (Sandbox Code Playgroud)

小智 -1

您的代码存在一些问题,我不明白为什么您createContext仍保留该组件<MyApp />

问题:

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

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

使用codesandbox 提供帮助会更容易。