Search code examples
react-hooks

Conditionally calling a hook in react


There is a rule in react about not calling a hook conditionally. AFAIK react only cares about the number of hooks called, so I tried this:

function useMainHook({ isLive }) {
  const res = isLive ? useHookA() : useHookB();
  return res;  // Make sure to return the result
}

If react only cares about how many hooks are called, this should work. Since there is always 1 hook being called.

Is the hook definition above valid?


Solution

  • react only cares about the number of hooks called

    React doesn't care about the number of hooks in it's own sake. React cares about the number of hooks because all hooks (within one component) need to be called in the same order for every render. Thus disallowing conditional hooks.

    If we run the below example we see that valueB is 0, although it should be 10. That is because both valueA and valueB are the second useState within App and so React can't distinguish them.

    import { useEffect, useState } from "react";
    
    const useHookA = () => {
      const [valueA] = useState(0);
      console.log("hook a", valueA);
      return valueA;
    }
    
    const useHookB = () => {
      const [valueB] = useState(10);
      console.log("hook b", valueB);
      return valueB;
    }
    
    function App() {
      const [hookA, setHookA] = useState(true);
      useEffect(() => {
        const i = setInterval(() => setHookA(v => !v), 1000);
        return () => clearInterval(i);
      }, []);
    
      const value = hookA ? useHookA() : useHookB();
    
      return (
        <p>Hook {hookA ? "A" : "B"}, value: {value}</p>
      );
    }