TypeError: Cannot read properties of undefined (reading 'createContext')

TypeError: Cannot read properties of undefined (reading 'createContext')

大家好,我正在寻求帮助。我在使用上下文 api 将数据从一个子组件传递到另一个子组件时遇到了一些麻烦。但是我得到了这个 typeError,到目前为止我尝试了一些搜索但运气不佳。如果有人不能指出我正确的方向,将不胜感激!

谢谢

CurrencyProvider.js

import { React, Component} from 'react';

export const MContext = React.createContext('');

class CurrencyProvider extends Component {

constructor() {
    super()
    this.state = {
        setinputValue: (value) => this.setState({ inputValue: value })
    }
}

render() {
    return (
        <MContext.Provider value={this.state}>
            {this.props.children}
        </MContext.Provider>)
}
}
export default CurrencyProvider;

Dropdown.js

import { useQuery, gql } from "@apollo/client";
import { useState } from "react";
import './Dropdown.scss';
import { MContext } from "../CurrencyProvider";

  const EXCHANGE_RATES = gql`
   query GetExchangeRates {
   rates(currency: "AUD") {
   currency
   rate
   name
  }
  }
 `;

  function Dropdown() {

const [isToggled, setToggle] = useState(false);

const { data, loading, error } = useQuery(EXCHANGE_RATES);

if (loading) {
    return <div>loading</div>;
}

if (error) {
    return <div>{error}</div>;
}

return (
    <div className="custom-dropdown"> 
        <ul className={`dropdown-menu ${isToggled ? 'open':''}`}> 
            <li value="0" className="first-item" onClick={() => setToggle(!isToggled)} onKeyPress={() => setToggle(!isToggled)} tabIndex="0">Select Currency:</li>
            {data.rates.map(({ currency, rate, name },index) => (
              <MContext.Consumer>
                {(context) => (
                  <li className="list-item" key={index} data={rate} tabIndex="0" onClick={()=>{context.setinputValue(rate)}}> <span>{name}: {currency}</span></li>
                )}
              </MContext.Consumer>
            ))}
        </ul>
    </div>
);
}

export default Dropdown;

Input.js

import './Input.scss';
import { MContext } from "../CurrencyProvider";

function Input() {
    return(
        <MContext.Consumer>
            {(context) => (
                <input value={context.state.inputValue} />
            )}
        </MContext.Consumer>
    );
}

export default Input;

CurrencyContainer.js

import Dropdown from '../Dropdown/Dropdown';
import Input from '../Input/Input';
import './CurrencyContainer.scss';
import CurrencyProvider from '../CurrencyProvider';

function CurrencyContainer() {
    return (
        <div className='currency-container'>
            <h1 >Select Items</h1>
            <div className="currency-wrapper">
                <CurrencyProvider>
                    <div><Input /></div>
                    <div><Dropdown /></div>
                    <div><Dropdown /></div>
                </CurrencyProvider>
            </div> 
        </div>
    );
}

export default CurrencyContainer;

App.js

import logo from './logo.svg';
import './App.scss';
import { client } from "./ApolloClient/client";
import { ApolloProvider } from '@apollo/client';
import CurrencyContainer from './CurrencyContainer/CurrencyContainer';


function App() {
  return (
    <ApolloProvider client={client}>
    <div className="App">
      <img src={logo} className="App-logo" alt="logo" />
      <CurrencyContainer /> 
    </div>
    </ApolloProvider>
  );
}

export default App;

您的 React 导入不正确。将其更改为:

import React, {Component} from 'react';

React 是默认导出,不是命名导出。

React 包没有名为 React 的命名导入,它具有人们通常使用 React 的默认导入,因此您应该更改此行

import { React, Component } from 'react';

至此

import React, { Component } from 'react';

如果您使用 React 17+,则不再需要 import React from 'react';,您可以从导入中删除对 React 的任何提及,因此您的导入将如下所示

import { createContext } from 'react';

但是您必须像这样在 .eslintrc.json 文件中关闭此导入的 lint 规则

{
    "rules": {
        ...
        "react/jsx-uses-react": "off",
        "react/react-in-jsx-scope": "off"
    }
}

你为什么不尝试将更多类似的东西放在一个单独的文件中 mcontext.context.jsx:

import { createContext } from "react";

const MContext = createContext('');

export default MContext;

然后就可以导入了

  • 通过导入新创建的上下文、useContext 挂钩并在封装在 MContext.Provider 节点中的功能组件顶部添加类似这样的内容来获取值:
const val = useContext(MContext);
  • 设置值:
<MContext.Provider value={mcontextValue}>

</MContext.Provider>

你的 MContext.Provider 节点内的所有子节点和他们的子节点都可以访问你的 MContext 值,因为我在答案的第一部分向你展示了它。