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

3

6

Hey all im looking for help. im having some trouble with passing data from one child component to another child component using the context api. But i get this typeError instead, i tried a few searches so far without much luck. if anyone can't point me in the right direction it would be much appreciated!

thanks

enter image description here 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;
Horseflesh answered 3/10, 2021 at 5:28 Comment(0)
M
7

Why don't you try placing something more in the likes of this in a separate file mcontext.context.jsx:

import { createContext } from "react";

const MContext = createContext('');

export default MContext;

Then you can import it and

  • get values by importing your newly created context, the useContext hook and adding something like this to the top of a functional component which is encapsulated inside a MContext.Provider node:
const val = useContext(MContext);
  • set values:
<MContext.Provider value={mcontextValue}>

</MContext.Provider>

All children inside your MContext.Provider node and their children will have access to your MContext value given you get it as I showed you in the 1st part of the answer.

Machismo answered 3/10, 2021 at 5:38 Comment(0)
L
5

Your React import is incorrect. Change it to:

import React, {Component} from 'react';

React is the default export, not a named export.

Lignin answered 3/10, 2021 at 5:31 Comment(0)
P
5

React package doesn't have a named import called React, it has a default import that people generally use React for, so you should change this line

import { React, Component } from 'react';

to this

import React, { Component } from 'react';

If you use React 17+, you don't need to import React from 'react'; anymore, you can remove any mentioning of React from your import, so your import will look like this

import { createContext } from 'react';

But you have to turn off the lint rules for this import in your .eslintrc.json file like so

{
    "rules": {
        ...
        "react/jsx-uses-react": "off",
        "react/react-in-jsx-scope": "off"
    }
}
Pamphylia answered 3/10, 2021 at 5:35 Comment(1)
This explains why we're getting the error and gives the simplest fix. This should be the selected answer!Oestrone

© 2022 - 2024 — McMap. All rights reserved.