Home > other >  Why does async function fail as soon as I reference value set by useParams react hook?
Why does async function fail as soon as I reference value set by useParams react hook?

Time:02-17

I'm trying to use the useParams hook to grab a value from the route and use it in an async handler function for my page which also uses useEffect and useState.

I noticed that my page works fine until I reference the value (pageId) that I got from useParams. As soon as you reference placeId within fetchPlaces you start getting this error:

React Hook useEffect has a missing dependency: 'fetchPlace'

I do not understand what's going on--why does it fail as soon as I reference the value set by the useParams hook?

import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";

function PlaceItem() {
  const { placeId } = useParams();
  const [place, setPlace] = useState([]);

  useEffect(() => {
    fetchPlace();
  }, []);

  async function fetchPlace() {
    /*** IF YOU DO NOT REFERENCE placeID IT WORKS ***/
    const placeData = await API.graphql({
      query: queries.getPlaceDetails,
      variables: { id: placeId },
    });
    setPlace(placeData);
  }

  return <Cards places={place} columns="1" />;
}

export default PlaceItem;

CodePudding user response:

You can also move fetchPlace inside the hook, as it's not used anywhere else.

import { useParams } from "react-router-dom";

function PlaceItem() {
  const { placeId } = useParams();
  const [place, setPlace] = useState([]);

  useEffect(() => {
    async function fetchPlace() {
     const placeData = await API.graphql({
      query: queries.getPlaceDetails,
      variables: { id: placeId },
     });

     setPlace(placeData);
    }

    fetchPlace();
  }, [placeId]);
 
  return <Cards places={place} columns="1" />;
}

export default PlaceItem;

CodePudding user response:

You try to hide it but placeId is a dependency of the effect. You may also consider useCallback around fetchPlace.

function PlaceItem() {
  const { placeId } = useParams();
  const [place, setPlace] = useState([]);

  useEffect(() => {
    fetchPlace(placeId); // ✅
  }, [placeId]); // ✅

  async function fetchPlace(placeId) {   // ✅
    const placeData = await API.graphql({
      query: queries.getPlaceDetails,
      variables: { id: placeId },
    });
    setPlace(placeData);
  }

  return <Cards places={place} columns="1" />;
}

Another answer suggest to write fetchPlace inside the effect but I think this is more sanitary.

function PlaceItem() {
  const { placeId } = useParams();
  const [place, setPlace] = useState([]);

  useEffect(() => {
    API.graphql({
      query: queries.getPlaceDetails,
      variables: { id: placeId },
    })
    .then(setPlace) // ✅
  }, [placeId]);

  return <Cards places={place} columns="1" />;
}
  • Related