Currently I’m wrangling with cleaning up my data fetching functions with useEffect.

I return a function that React can run when it unmounts, see React Documentation.

In my example, I use the didCancel Boolean from this article.

Unfortunately, it doesn’t work and still fetches data even if I navigate away from the page that uses the custom data fetching hook.

import { useEffect, useReducer } from "react";
import { API, graphqlOperation } from "aws-amplify";
import { getMarket } from "../../graphql/queries";

const useFetchMarketData = ({ marketId, user }) => {
  const [state, dispatch] = useReducer(marketFetchReducer, {
    isLoading: true,
    isError: false,
    market: null,
    isMarketOwner: false
  });

  function marketFetchReducer(state, action) {
    switch (action.type) {
      case "FETCH_INIT":
        return {
          ...state,
          isLoading: true,
          isError: false
        };
      case "FETCH_SUCCESS":
        return {
          ...state,
          isLoading: false,
          isError: false,
          market: action.payload,
          isMarketOwner: user.username === action.payload.owner
        };
      case "FETCH_FAILURE":
        return {
          ...state,
          isLoading: false,
          isError: true
        };
      default:
        throw new Error();
    }
  }

  useEffect(() => {
    let didCancel = false;

    const fetchMarket = async () => {
      dispatch({ type: "FETCH_INIT" });
      try {
        const input = { id: marketId };
        const result = await API.graphql(graphqlOperation(getMarket, input));
        if (!didCancel) {
          dispatch({
            type: "FETCH_SUCCESS",
            payload: result.data.getMarket
          });
        }
      } catch (error) {
        if (!didCancel) {
          dispatch({ type: "FETCH_FAILURE" });
        }
      }
    };
    fetchMarket();
    return () => {
      didCancel = true;
    };
  }, [dispatch, marketId]);

  return { ...state };
};

export default useFetchMarketData;

Further Reading