Search code examples
reactjsreact-nativereact-hooksuse-effect

How to chain API requests in useEffect() with custom hooks?


  • I'm trying to fetch a user's latitude and longitude coordinates and then using those coordinates make a search request inside of useEffect()
  • location is always null when useResults executes and this is the problem
  • useResults and fetchLocation both work individually but I'm having trouble chaining them together
  • Any thoughts would be appreciated, thanks
My Code (I'm trying to do something like this)
    const [fetchLocation, location, message] = useLocation()
    const [fetchResults, searchResults, isSearchError] = useResults()

    useEffect(() => {
        fetchLocation()                    // get user longitude and latitude, set longitude and latitude data into "location"
        useResults({
             location.coords.longitude, 
             location.coords.latitude })   // feed longitude and latitude data into useResults
    }, [])

useResults.js
const useResults = () => {
    const [searchResults, setSearchResults] = useState([])
    const [isSearchError, setIsSearchError] = useState(false)

    const fetchResults = async (
        searchTerm,
        { latitude, longitude }
    ) => {
        try {
            // get search data
            const response = await yelpAPI.get("/search", {
                params: {
                    limit: 50,
                    term: searchTerm,
                    latitude,
                    longitude
                }
            })
            // set search data
            setSearchResults(response.data.businesses)
        } catch (err) {
            console.log(err)
            console.log("Something went wrong in useResults.js")
            setIsSearchError(true)
        }
    }

    return [fetchResults, searchResults, isSearchError]
}

useLocation.js
const useLocation = () => {
    const [location, setLocation] = useState(null)
    const [message, setMessage] = useState(
        "Fetching user location data"
    )

    const fetchLocation = async () => {
        try {
            let { status } =
                await Location.requestForegroundPermissionsAsync()

            if (status !== "granted") {
                setErrorMsg(
                    "Permission to access location was denied"
                )
                return
            }
            // get user location data
            let locationData = await Location.getCurrentPositionAsync(
                {}
            )
            setMessage(null)
            // set user location data
            setLocation(locationData)
        } catch (err) {
            console.log(err)
            setMessage("Fetching user location failed")
        }
    }

    return [fetchLocation, location, message]
}


Solution

  • You need two useEffect. one is gonna run on mount:

      useEffect(() => {
        fetchLocation()                    // get user longitude and latitude, set longitude and latitude data into "location"
      }, [])
    

    and one that is gonna run when the location is fetched & has a value:

      useEffect(() => {
        if (location)
          fetchResults({location.coords.longitude, 
            location.coords.latitude})                    // get user longitude and latitude, set longitude and latitude data into "location"
      }, [location])