I need to send selectedCoin
state from Company
to details.js
How do I do this with context
?
company component:
import React, { useState, useEffect } from "react"; import { Col, Image, Row } from "react-bootstrap"; import "./Company.scss"; // * api import { getCoin } from "../services/api"; // *spinner import Loader from "./Loader"; const Company = () => { const [selectedCoin, setSelectedCoin] = useState(null); const [coins, setCoins] = useState([]); useEffect(() => { const fetchAPI = async () => { const data = await getCoin(); setCoins(data); }; fetchAPI(); }, []); const coinId = () => { console.log(selectedCoin); }; coinId(); return ( <> {coins.length > 0 ? ( coins.map((coin) => ( <Row className={ selectedCoin === coin.id ? "p-2 pe-3 border-top d-flex align-items-center company-list-single-active" : "p-2 border-top d-flex align-items-center company-list-single" } onClick={() => { setSelectedCoin(coin.id); // console.log(coin.id); // console.log(coin.name); }} key={coin.id} > <Col xxl="2" xl="2" lg="3" md="3" sm="2" xs="2"> <Image src={coin.image} alt={coin.name} className="coin-image mx-2" fluid /> </Col> <Col> <span>{coin.name}</span> </Col> </Row> )) ) : ( <Loader /> )} </> ); }; export default Company;
details components:
import React, { useState, useEffect } from "react"; import axios from "axios"; const Details = () => { const [data, setData] = useState({ name: "", id: "", }); const apiDetails = async () => { await axios .get(`https://api.coingecko.com/api/v3/coins/${"ethereum"}`) .then((r) => { // console.log(response); setData({ name: r.data.name, id: r.data.id, }); return setData; }); }; useEffect(() => { (async () => { const response = await apiDetails(); setData({ name: response.data.name, id: response.data.id, }); })(); }, []); return ( <div> <h1>{data.name}</h1> <h1>{data.id}</h1> </div> ); }; export default Details;
Advertisement
Answer
Well, looks like you’re just interested on the code right, so I’ll just drop the code in here. Obviously, feels free to move code around and make sure you use the syntax that does make sense to you
This is the context
CoinsContext.js
import React, { createContext, useContext, useState, useEffect } from "react"; import { getCoin } from "@api"; const CoinsContext = createContext({}); export const CoinsContextProvider = ({ children }) => { const [selectedCoin, setSelectedCoin] = useState(null); const [coins, setCoins] = useState([]); useEffect(() => { const fetchAPI = async () => { const data = await getCoin(); setCoins(data); }; fetchAPI(); }, []); return ( <CoinsContext.Provider value={{ selectedCoin, setSelectedCoin, coins }}> {children} </CoinsContext.Provider> ); }; export const useCoins = () => useContext(CoinsContext);
To use it, you need to wrap up all the pages that are gonna use the context with it, for example, since you want Details.js and Company.js to use it, you will need to wrap both pages with it. I’ll just wrap the entire App, which means the entire app can use it, but feel free to do what you want.
Would be something like this:
index.js
import React from "react"; import ReactDOM from "react-dom"; import App from "./App"; import { CoinsContextProvider } from "./CoinsContext"; ReactDOM.render( <React.StrictMode> <CoinsContextProvider> <App /> </CoinsContextProvider> </React.StrictMode>, document.getElementById("root") );
Now we have the CoinsContext set up, we can use it on your components
Company.js
import React from "react"; import { Col, Image, Row } from "react-bootstrap"; import "./Company.scss"; // *spinner import Loader from "./Loader"; import { useCoins } from "./CoinsContext"; const Company = () => { const { coins, selectedCoin, setSelectedCoin } = useCoins(); return ( <> {coins.length > 0 ? ( coins.map((coin) => ( <Row className={ selectedCoin === coin.id ? "p-2 pe-3 border-top d-flex align-items-center company-list-single-active" : "p-2 border-top d-flex align-items-center company-list-single" } onClick={() => { setSelectedCoin(coin.id); // console.log(coin.id); // console.log(coin.name); }} key={coin.id} > <Col xxl="2" xl="2" lg="3" md="3" sm="2" xs="2"> <Image src={coin.image} alt={coin.name} className="coin-image mx-2" fluid /> </Col> <Col> <span>{coin.name}</span> </Col> </Row> )) ) : ( <Loader /> )} </> ); }; export default Company;
Details.js
import React, { useState, useEffect } from "react"; import axios from "axios"; import { useCoins } from "./CoinsContext"; const Details = () => { const { selectedCoin, coins, setSelectedCoin } = useCoins(); const [data, setData] = useState({ name: "", id: "", }); const apiDetails = async () => { await axios .get(`https://api.coingecko.com/api/v3/coins/${"ethereum"}`) .then((r) => { // console.log(response); setData({ name: r.data.name, id: r.data.id, }); return setData; }); }; useEffect(() => { (async () => { const response = await apiDetails(); setData({ name: response.data.name, id: response.data.id, }); })(); }, []); return ( <div> <h1>{data.name}</h1> <h1>{data.id}</h1> </div> ); }; export default Details;
And we’re done! Now you are not just sharing selectedCoin between your components, but you’re also putting all coins fetching logic in your context, which overall is the right thing to do