1

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;

  • Possible duplicate? https://stackoverflow.com/questions/55840294/how-to-fix-missing-dependency-warning-when-using-useeffect-react-hook Not quite, but the information included within is useful. – Kevin B Feb 16 '22 at 20:28
  • Yeah, I've looked all over and I tried that. I get the same result--I can run it without referencing placeId, but as soon as I use that variable it starts failing. I'm trying to understand why it's happening, and have read several articles on how hooks work but I'm clueless. All of the examples I see using getParams are super simple and not async. – ZekeTheGeek Feb 16 '22 at 20:34
  • My understanding, is that because you're relying on a value defined outside of the hook, the linter expects the hook to depend on that value. You can disable the rule for this specific case if you're sure it won't lead to any issues. – Kevin B Feb 16 '22 at 20:35
  • From what I can tell, `fetchPlace` is already a missing dependency even before referencing the `placeId` variable. What is actually failing? Both `fetchPlace` and `placeId` appear to be dependencies. – Drew Reese Feb 16 '22 at 20:50

2 Answers2

1

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" />;
}
よつば
  • 467
  • 1
  • 8
  • For what it's worth it didn't seem to matter where the function was declared, just the reference to the variable. What fixed it was passing in the dependency, as you demonstrated here. Thanks! – ZekeTheGeek Feb 16 '22 at 21:15
  • It is my pleasure to assist. You might also think about how to handle potential errors. – よつば Feb 16 '22 at 21:18
1

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;
MAP
  • 397
  • 2
  • 8