0

I have a react component displaying details about a trip. The component queries the db for this data in 2 consecutive queries. The first query includes a destination_id and a list of participant ids. The second query uses that destination_id to get details on the destination. I am storing the details in React state variables. The second query thinks tripDetails.destination_id is undefined. I think this means the first function's call to setTripDetails() has not completed before the second query starts.

Here was my original code...

  useEffect(() => {
    const getTrip = async () => {
      try {
        const response = await api.get('/trips/' + trip_id, { trip_id: trip_id });
        setTripDetails(response.data);
      } catch (err) {
        Alert.alert('This trip could not be found. id=' + trip_id);
        console.log('error fetching trip details: ' + JSON.stringify(err.response.data));
      }
    };
    const getDestination = async () => {
      try {
        const response = await api.get('/destinations/' + tripDetails.destination_id);
        setDestination(response.data);
      } catch (err) {
        console.log('error fetching destination details: ' + JSON.stringify(err.response.data));
      }
    };

    const getAllTripDetails = async () => {
      setIsLoading(true);
      await getTrip();
      await getDestination();
      setIsLoading(false);
    };
    getAllTripDetails();
  }, []);

I tried refactoring according to option 1 in David's answer on this similar stack overflow question. as follows...

  useEffect(() => {
    const getTrip = async () => {
      console.log('getting trip');
      try {
        setIsLoading(true);
        const response = await api.get('/trips/' + trip_id, { trip_id: trip_id });
        setTripDetails(response.data);
        setIsLoading(false);
      } catch (err) {
        console.log('error fetching trip details: ' + JSON.stringify(err.response.data));
      }
    };
    getTrip();
  });

  useEffect(() => {
    const getDestination = async () => {
      console.log('getting destination');
      try {
        const response = await api.get('/destinations/' + tripDetails.destination_id);
        setDestination(response.data);
      } catch (err) {
        console.log('error fetching destination details: ' + JSON.stringify(err.response.data));
      }
    };

    if (tripDetails) {
      getDestination();
    }
  }, [tripDetails]);

This works, but I'm not sure I am using the useEffect hooks 100% correctly such that this won't cause other problems down the line.

GNG
  • 1,341
  • 2
  • 23
  • 50
  • 2
    Your first `useEffect` needs also `[trip_id]` as second parameter. Currently it will execute on every rerender. – Sysix Apr 24 '22 at 20:33
  • 1
    Reference the first API result directly instead of referencing the stateful variable, which has not updated due to the stale closure. I think a single effect hook would make a bit more sense. Your first code was almost there. – CertainPerformance Apr 24 '22 at 20:44
  • 1
    In the first useEffect, pass an empty array as dependency if you want to run it only once: ```js useEffect(() => { const getTrip = async () => { console.log('getting trip'); try { setIsLoading(true); const response = await api.get('/trips/' + trip_id, { trip_id: trip_id }); setTripDetails(response.data); setIsLoading(false); } catch (err) { console.log('error fetching trip details: ' + JSON.stringify(err.response.data)); } }; getTrip(); }, []); ``` – GeekyCode Apr 24 '22 at 22:38

0 Answers0