Search code examples
javascriptreactjsapireact-hooksreact-props

Fetching the charities using the global giving API using react


I'm using global giving API to make a charity finder app.

I have two dropdowns and a search button in the CharityFinderPage.js component. Now on clicking the search button, I want to fetch the charities using the themeId. The endpoint is https://api.globalgiving.org/api/public/projectservice/themes/{themeId}/projects

I know that on handleClick I should fetch the charities, but how do I get the value of themeId in the handleClick of CharityFinderPage.js component.

What I want is to show a new card component when the button clicks like showing a charity card with the fields populated on it from the data of the API, but first I need to be able to get the data from the API, then I can render a new component.

Here's the code:



CharityFinderPage.js

const CharityFinderPage = () => {

  const handleClick = () => {
    console.log("inside handleclick")
  }

  return (
    <div style={containerStyle}>
      <h1>Charity Finder ❤️</h1>
      <h3>Search for charity</h3>
      <h4>
        Filter charities by personal search conditions. Use the dropdown below
        to see charities matching your criteria.
      </h4>

      <Themes />
      <Regions />
      <button onClick={handleClick}>Search</button>
    </div>
  )
}

export default CharityFinderPage

Themes.js

import React, { useEffect, useState } from "react"
import axios from "axios"
const url = `https://api.globalgiving.org/api/public/projectservice/themes.json?api_key=${process.env.REACT_APP_api_key}`

const Themes = () => {
  const [isLoading, setIsLoading] = useState(false)
  const [selectValue, setSelectValue] = useState("")
  const [themes, setThemes] = useState([])

  useEffect(() => {
    const fetchThemes = async () => {
      try {
        setIsLoading(true)
        const result = await axios.get(url)
        setThemes(result.data.themes.theme)
        setIsLoading(false)
      } catch (err) {
        console.log(err)
      }
    }
    fetchThemes()
  }, [])

  const handleChange = (event) => {
    console.log("inside handleChange", event.target.value)
    setSelectValue(event.target.value)
  }

  return (
    <div>
      {isLoading ? (
        <h4>Loading......</h4>
      ) : (
        <div>
          <label>Select theme: </label>
          <select onChange={handleChange} value={selectValue}>
            {themes.map((theme, id) => {
              return <option key={id}>{theme.name}</option> //{id} is the `themeId`
            })}
          </select>
        </div>
      )}
    </div>
  )
}

export default Themes

Regions component is exactly similar to Themes.


Solution

  • So the thing that you need to do here is called lifting the state up.

    You need to move your states of theme component to CharityFinder component

    I am lifting only selectedValue because that is all that you need

    CharityFinderPage.js

    const CharityFinderPage = () => {
    
      const [selectValue, setSelectValue] = useState("")
    
    
    
      const handleClick = () => {
        console.log(`inside handleclick with ${selectValue}`)
      }
    
      return (
        <div style={containerStyle}>
          <h1>Charity Finder ❤️</h1>
          <h3>Search for charity</h3>
          <h4>
            Filter charities by personal search conditions. Use the dropdown below
            to see charities matching your criteria.
          </h4>
    
    // you can pass the setSelectValue as prop to Themes component
          <Themes setSelectValue={setSelectValue} selectValue={selectValue} />
          <Regions />
          <button onClick={handleClick}>Search</button>
        </div>
      )
    }
    
    export default CharityFinderPage
    

    Theme.js

    import React, { useEffect, useState } from "react"
    import axios from "axios"
    const url = `https://api.globalgiving.org/api/public/projectservice/themes.json?api_key=${process.env.REACT_APP_api_key}`
    
    const Themes = ({ selectValue, setSelectValue }) => {
      const [isLoading, setIsLoading] = useState(false)
      const [themes, setThemes] = useState([])
    
      useEffect(() => {
        const fetchThemes = async () => {
          try {
            setIsLoading(true)
            const result = await axios.get(url)
            setThemes(result.data.themes.theme)
            setIsLoading(false)
          } catch (err) {
            console.log(err)
          }
        }
        fetchThemes()
      }, [])
    
      const handleChange = (event) => {
        console.log("inside handleChange", event.target.value)
        setSelectValue(event.target.value)
      }
    
      return (
        <div>
          {isLoading ? (
            <h4>Loading......</h4>
          ) : (
            <div>
              <label>Select theme: </label>
              <select onChange={handleChange} value={selectValue}>
                {themes.map((theme, id) => {
                  return <option key={id}>{theme.name}</option> //{id} is the `themeId`
                })}
              </select>
            </div>
          )}
        </div>
      )
    }
    
    export default Themes