首页 > 解决方案 > Memoize 自定义钩子的返回值

问题描述

我有一个像这样的自定义 React 钩子:

export default function useLocations(locationsToMatch) {
  const state = useAnotherHookToGetStateFromStore();
  const { allStores } = state.locations;

  const allLocations = {};
  allStores.forEach((store) => {
    const { locationId, locationType } = store;
    const isLocationPresent = locationsToMatch.indexOf(locationId) !== -1;
    if (isLocationPresent && locationType === 'someValue') {
      allLocations[locationId] = true;
    } else {
      allLocations[locationId] = false;
    }
  });

  return allLocations;
}

当我在我的 React 组件中使用上面的钩子时,如下所示:

const locations = useLocations([908, 203, 678]) // pass location ids

由于无限渲染,我得到一个最大调用深度错误。这是因为我的组件中有一些代码使用useEffect如下钩子:

useEffect(() => { // some code to re-render component on change of locations
   }, [locations])

所以我试图将我的返回值包装在useLocations钩子中,useMemo如下所示:

export default function useLocations(locationsToMatch) {
  const state = useAnotherHookToGetStateFromStore();
  const { allStores } = state.locations;

  const allLocations = {};
  const getStores = () => {
    allStores.forEach((store) => {
      const { locationId, locationType } = store;
      const isLocationPresent = locationsToMatch.indexOf(locationId) !== -1;
      if (isLocationPresent && locationType === 'someValue') {
        allLocations[locationId] = true;
      } else {
        allLocations[locationId] = false;
      }
    });
    return allLocations;
  };

  return useMemo(() => getStores(), [locationsToMatch, state]);
}

但这仍然会导致消费组件的无限重新渲染。那么如何从我的自定义钩子中返回一个记忆值useLocations以防止无限重新渲染?

标签: reactjs

解决方案


推荐阅读