exhaustive-deps infinite loop with function dependant on component state

214 Views Asked by At

Given the following example

const SettingsLayout = () => {
  const [tabs, setTabs] = useState(SettingsNavigation);
  const router = useRouter();

  const updateActiveTab = useCallback(
    (pathname) => {
      setTabs(
        tabs.map((tab: Tab) => ({
          ...tab,
          current: tab.href === pathname,
        }))
      );
    },
    [tabs]
  );

  useEffect(() => {
    updateActiveTab(router.pathname);
  }, [router.pathname]);
  // exhaustive-deps wants me to add updateActiveTab to the dependency array
  // but adding it will cause an infinite render loop
  // Flux:
  //   -> useEffect will change tabs
  //   -> tabs will change updateActiveTab
  //   -> updateActiveTab will execute useEffect

  return (...)
}

So far i have not found a solution other than disabling exhaustive-deps, i've read you shouldn't do it.

How can i execute updateActiveTab only when router.pathname changes?

1

There are 1 best solutions below

2
On BEST ANSWER

Check this out!

const SettingsLayout = () => {
  const allTabs = SettingsNavigation;
  const [tabs, setTabs] = useState();
  const router = useRouter();

  const updateActiveTab = useCallback(
    (pathname) => {
      setTabs(
        allTabs.map((tab: Tab) => ({
          ...tab,
          current: tab.href === pathname,
        }))
      );
    },
    [allTabs]
  );

  useEffect(() => {
    updateActiveTab(router.pathname);
  }, [router.pathname]);

  return (...)
}