React, use custom hook donditionally, but not quite?

Hey everyone!
Im into exploring some more advanced React use cases and while using hooks conditionally is anti-pattern, I was wondering if something like the code beneath is appropriate to use. It looks like it does not go against React restrictions and hooks misbehavior, as long as we dont use the hook, but only conditionally reference it:

const useHookOne = () => // do something
const useHookTwo = () => // do something else

const MyComponent = ({ bool }) => {
  const conditionalHook = bool ? useHookOne : useHookTwo
  const data = conditionalHook()
  
  return <div>{data}</div>
}

Furthermore, we cant call custom hook within other hooks(e.g. useMemo), but if we want to memoize the value returned by the hook(so we dont have to redo its logic), what would be possible solution? Memoizing its returned value alone wont do much, if calculations are still done?

I was thinking something like, beneath code, but if I read it correct, it does memoize the callback, but not the value returned after being executed:

const useHookOne = () => // do something
const useHookTwo = () => // do something else

const MyComponent = ({ bool }) => {
  const data = useMemo(() => bool ? useHookOne : useHookTwo, [bool])() 
  
  return <div>{data}</div>
}

Every hook should be run on every rerender. You cannot use hooks conditionally. I’m assuming that this is because a hook needs to reconfirm/recalculate its state and know whether or not to force the component to update. If you start hiding hooks, it can’t do that.

Is there a specific use case you are imagining or is this just theoretical?

Hooks need to run in the same order (call index).

useMemo caches the value, if the dependencies do not change there is no need to re-calculate the value.

React will return the same value again if the dependencies have not changed since the last render.

Regarding first code snippet, its actually pulled from real use case, where I had two different custom hooks return a callback and depending on a boolan flag, we would use either the callback of hookA, or hookB. Instead of running both hooks every render, grabbing both callbacks and consider which one to use, I wanted to determine which hook is appropriate to utilize dpending on the boolean flag and use the hook after. I.e. I use only one of the hooks, but its not bool ? hookA() : hookB(), it only changes the reference: hook = bool ? hookA : hookB and call it afterwards(non-conditionally): hook()
And the idea behind the second code snippet(but not quite established), is to memoize the value returned by the hook, so I dont have to call the hook everytime, but suppose thats conditional hook rendering. Memoizing the returned value within the hook itself, would only memoize the value, but not the calculations before that, or im missing something, I guess meant to prevent components from rerender as they recognise its the same object, but ultimately letting the hook does its calculations nevetheless.

But you can’t do that, by design. All hooks have to run on each render. Hooks, by definition, have state - otherwise they’d just be functions. They have to run on each render to confirm that they have the correct state so that the component can know if it needs to rerender, and other things that rely on them know if they have to run and update.

Just because a hook is running doesn’t mean that it is doing much. It may just be doing a check to see if the dependencies have changed. And internally, inside the hook (if it’s a custom hook) you can determine what gets done and what doesn’t. That’s what dependencies are for.

You are trying to do the logic outside the hook. I would either have two custom hooks that each determine for themselves when they run, or wrap them both in another custom hook and have all the logic there.

Hooks are a different way of thinking - it took me a while to wrap my head around them and their logic. But you can do some really cool things with them once you get a hang of it. Yes, sometimes it seems inefficient, but probably a lot less than we think.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.