Search code examples
javascriptreactjstwitter-bootstrapreact-functional-componentreact-context

How to call functions from components in context API?


I just began using Context API in React.JS and am still learning it. I have a button in my navbar child functional component which when pressed, I want it to send data to my context api which is used in a function. This is my Context API

import {useState, createContext} from 'react'

export const ContextApi = createContext()

export const ApiProvider = props => {
    const [api, setApi] = useState({
        winners: [
            {
                id: 1930,
                winningTeam: "Uruguway",
                runnerUp: "Argentina",
                location: "Montevideo, Uruguay",
                Attendance: "80,000",
                score: "4-2"
            },
            {
                id: 1934,
                winningTeam: "Italy",
                runnerUp: "Czechoslovakia",
                location: "Rome, Italy",
                Attendance: "50,000",
                score: "2-1"
            },
            {
                id: 1938,
                winningTeam: "Italy",
                runnerUp: "Hungary",
                location: "Colombes, France",
                Attendance: "45,000",
                score: "4-2"
            },
            {
                id: 1950,
                winningTeam: "Uruguway",
                runnerUp: "Brazil",
                location: "Rio De Janeiro, Brazil",
                Attendance: "199,854",
                score: "2-1"
            },
            {
                id: 1954,
                winningTeam: "West Germany",
                runnerUp: "Hungary",
                location: "Bern, Switzerland",
                Attendance: "60,000",
                score: "3-2"
            },
            {
                id: 1958,
                winningTeam: "Brazil",
                runnerUp: "Sweden",
                location: "Solna, Sweden",
                Attendance: "51,800",
                score: "5-2"
            },
            {
                id: 1962,
                winningTeam: "Brazil",
                runnerUp: "Czechoslovakia",
                location: "Santiago, Chile",
                Attendance: "69,000",
                score: "3-1"
            },
            {
                id: 1966,
                winningTeam: "England",
                runnerUp: "West Germany",
                location: "London, England",
                Attendance: "96,924",
                score: "4-2"
            },
            {
                id: 1970,
                winningTeam: "Brazil",
                runnerUp: "Italy",
                location: "Mexico City, Mexico",
                Attendance: "107,412",
                score: "4-1"
            },
            {
                id: 1974,
                winningTeam: "West Germany",
                runnerUp: "Netherlands",
                location: "Munich, West Germany",
                Attendance: "75,200",
                score: "2-1"
            },
            {
                id: 1978,
                winningTeam: "Argentina",
                runnerUp: "Netherlands",
                location: "Buenos Aires, Argentina",
                Attendance: "71,483",
                score: "3-1"
            },
            {
                id: 1982,
                winningTeam: "Italy",
                runnerUp: "West Germany",
                location: "Madrid, Spain",
                Attendance: "90,000",
                score: "3-1"
            },
            {
                id: 1986,
                winningTeam: "Argentina",
                runnerUp: "West Germany",
                location: "Mexico City, Mexico",
                Attendance: "114,600",
                score: "3-2"
            },
            {
                id: 1990,
                winningTeam: "West Germany",
                runnerUp: "Argentina",
                location: "Rome, Italy",
                Attendance: "73,603",
                score: "1-0"
            },
            {
                id: 1994,
                winningTeam: "Brazil",
                runnerUp: "Italy",
                location: "Pasadena, United States",
                Attendance: "94,194",
                score: "0-0"
            },
            {
                id: 1998,
                winningTeam: "France",
                runnerUp: "Brazil",
                location: "Saint-Denis, France",
                Attendance: "80,000",
                score: "3-0"
            },
            {
                id: 2002,
                winningTeam: "Brazil",
                runnerUp: "Germany",
                location: "Yokohama, Japan",
                Attendance: "69,029",
                score: "2-0"
            },
            {
                id: 2006,
                winningTeam: "Italy",
                runnerUp: "France",
                location: "Berlin, West Germany",
                Attendance: "69,000",
                score: "1-1"
            },
            {
                id: 2010,
                winningTeam: "Spain",
                runnerUp: "Netherlands",
                location: "Johannesburg, South Africa",
                Attendance: "84,490",
                score: "1-0"
            },
            {
                id: 2014,
                winningTeam: "Germany",
                runnerUp: "Argentina",
                location: "Rio De Janeiro, Brazil",
                Attendance: "74,738",
                score: "1-0"
            },
            {
                id: 2018,
                winningTeam: "France",
                runnerUp: "Croatia",
                location: "Moscow, Russia",
                Attendance: "78,011",
                score: "4-2"
            }
            
        ],
        country: null
    })
    const addCountry = (country) => {
        console.log(country)
    }
    return (
        <ContextApi.Provider addCountry={addCountry()} value={{winnerData: [api, setApi]}}>{props.children}</ContextApi.Provider>
    )
}

This is my Main File

const Main = () => {
    return (
        <ApiProvider>
            {/*NAVIGATION BAR*/}
            <FifaNavbar />
            {/*MAIN IMAGE AND TEXT*/}
            <TitleArea />
            {/*EACH YEAR'S WINNER CARDS*/}
            <WinnerCards />
            {/*Extra Space On The Bottom*/}
            <div style={{height: "400px"}}></div>
        </ApiProvider>
    )
}

export default Main

and this is my navigation bar file

import { useState } from "react";
import { Navbar, Nav, NavDropdown, Form, FormControl, Button, Container} from "react-bootstrap"
const FifaNavbar = ( {addCountry} ) => {
  const [country, setCountry] = useState(null)
  setTimeout(() => {
    document.getElementById("disabled").setAttribute("disabled", true)
  }, 0);
    return (
    <Navbar variant="dark" expand="md" className="navbar mb-5">
      <Container>
  <Navbar.Brand href="/">World Cup Winners</Navbar.Brand>
  <Navbar.Toggle aria-controls="basic-navbar-nav" />
  <Navbar.Collapse id="basic-navbar-nav">
    <Nav className="mr-auto">
      <Nav.Link href="#home">Countries</Nav.Link>
      <Nav.Link href="#link">Link</Nav.Link>
    </Nav>
    <Form inline>
    <Form.Group controlId="exampleForm.ControlSelect1" >
    <Form.Control as="select" onChange={e => setCountry(e.target.value)} >
    <option id="disabled">Search Countries</option>
      <option>Brazil</option>
      <option>Germany</option>
      <option>Italy</option>
      <option>Argentina</option>
      <option>France</option>
      <option>Uruguay</option>
      <option>England</option>
      <option>Spain</option>
      <option>Netherlands</option>
      <option>Czechoslovakia</option>
      <option>Hungary</option>
      <option>Sweden</option>
      <option>Croatia</option>
    </Form.Control>
  </Form.Group>
      <Button variant="outline-light" onClick={() => {addCountry({country})}} >Search</Button>
    </Form>
  </Navbar.Collapse>
  </Container>
</Navbar>
    )
}

export default FifaNavbar

I want that when I press the button in my navbar

<Button variant="outline-light" onClick={() => {addCountry({country})}} >Search</Button>

It will send the value of country in my state with the function addCountry() to my context API where I can console.log() it

Thank You For Your Help


Solution

  • first you need to change the way you are using the Context provider which doesn't get any other props than value.

    <ContextApi.Provider value={{winnerData: api, setWinnerData: setApi, addCountry: addCountry}}>{props.children}</ContextApi.Provider>
    

    then you need to import useContext in your navigation bar component:

    import { ContextApi }  from "YOUR_CONTEXT_API_DIRECTORY";
    
    const FifaNavbar = () => {
      const { addCountry } = React.useContext(ContextApi);
      //...
    }