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
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;
CodePudding user response:
Your React
import is incorrect. Change it to:
import React, {Component} from 'react';
React
is the default export, not a named export.
CodePudding user response:
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"
}
}
CodePudding user response:
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.