Hook keep redrawing the component infinitely

Viewed 32

In React 18, have a generic hook that is supposed to pickup any graphql query, and do some manipulation to load and display a set of options.

It currently look like this.


export const useOptionsLoader = <Q extends RequiredResponse, V extends RequiredVariables>({
  lazyQuery,
  variables,
  mapOptions,
}: LoadSelectOptionsProps<Q, V>) => {
  const loadOptions = useCallback(
    async (keyword: string, extra = { page: 0 }) => {
      // Do an API fetch on `lazyQuery` using `variables`
      // then pass the result to `mapOptions` to create a list of options
    },
    [lazyQuery, mapOptions, variables]
  );

  return loadOptions;
};

I can call it with some options inside my component

  const [getOptions] = useOptionsListLazyQuery();
  const loadOptions = useOptionsLoader<OptionsListQuery, OptionsListQueryVariables>({
    lazyQuery: getOptions,
    variables: {
      sortBy: {
        descending: true,
        field: 'updated',
      },
    },
    mapOptions: (data) => {
      const options = data?.options?.items.map(({ id: value, name: label }) => ({
        value,
        label,
      }));
      return options || [];
    },
  });

the problem I face is, when using two hook on the same component (it probably exist also with one hook, but for some reason its only breaking the app when using 2)

  const [getOptions1] = useOptionsList1LazyQuery();
  const loadOptions1 = useOptionsLoader<OptionsListQuery, OptionsListQueryVariables>({
    lazyQuery: getOptions1,
    variables: { // something },
    mapOptions: () => [] // something 
  })
  const [getOptions2] = useOptionsList2LazyQuery();
  const loadOptions2 = useOptionsLoader<OptionsList2Query, OptionsList2QueryVariables>({
    lazyQuery: getOptions2,
    variables: { // something },
    mapOptions: () => [] // something 
  })


  <Component loadOptions={loadOptions1} />
  <Component2 loadOptions={loadOptions2} />

My hook's keep getting "redrawn" because the props variables and mapOptions keep getting "reassigned" even thos they are exactly the same. Probably they are just "shallow same" but not having the exact same reference.

Result is, my hook keep getting called so the loadOptions keep changing and the query keep getting called infinitely.

Is there something to prevent this without having to wrap useMemo on everything ?

0 Answers
Related