You Can't Call Hooks Inside Conditions? Yes you can

### tl;dr

* Calling hooks conditionally breaks the rules, yes.
* Wrap the hook with a component and render that component optionally to toggle the usage of the hook.
* The rules of hooks are somewhat reflections of the constraints of this React API.
* Example final full code [here](https://goodguydaniel.com/blog/call-react-hooks-inside-condition#example-full-code).

!["forbidden seagull bending the rules"](https://goodguydaniel.com/static/b8e546a2708057c57a553031ddd22a45/6a8a8/forbidden-seagull.png ""forbidden seagull bending the rules"")

### Bending the Rules

There's a [bunch of reasons why you can't use a React hook conditionally](https://reactjs.org/docs/hooks-rules.html) under a particular condition.

Before I start, I would like you to take a moment to reflect on the following questions?

**Why did you end up needing this? And, is it your fault, or is it the library's fault?**

When I first tried to answer the question myself, I settled that it would be my fault If I had written the code since the very beginning. If you pick React hooks API, you should structure the code accordingly not to end up falling into such scenarios where your better option might be breaking the rules. On the other end, if you have hundreds of components combined in a large shared codebase, you might hit a dead end where the most optimal option for the time being it's not beautiful. Still, it gets the job done and buys you and your team time to get things out faster, ideally you would come back and remove the hack later. Still, most of the time in the real world, we know that's not going to happen, so you better documenting it properly to alleviate the unavoidable spike on *WTFs/minute* (got this from [Clean Code by Robert C. Martin](http://cleancoder.com/products)).

!["code review cartoon"](https://goodguydaniel.com/static/2f6359f88f008b90d664db8b93568f73/32181/wtfs-per-minute-code-review.png ""code review cartoon"")

"*Are we debugging in a panic, poring over code that we thought worked?*" \n - [Clean Code by Robert C. Martin](http://cleancoder.com/products)

As always, I think there's nothing better than an example to explain a concept, let's look into one.

In this example, we have a custom hook `useRandomNumberEverySecond` that produces a random number every one second. In a real scenario, you could potentially have a super sophisticated hook that performs asynchronous stuff like data fetching and puts everything together. For the sake of simplicity, we're just returning a number.

We want only to call on `useRandomNumberEverySecond` and use its result, if and only if, a flag `isHookActive` has value `true`. But, how can we achieve this if we declare hooks at the top level of a component, and we can't wrap them inside `if` statements?

My suggested approach is to wrap our hook `useRandomNumberEverySecond` in a second component, `RandomNumberWrapper`, that mediates the relationship between our target component and the hook `useRandomNumberEverySecond`. Let's see how that looks.

source: © 2022 by goodguydaniel.com

\
As proof of concept, the goal is to have the button in the interface toggle the usage of our custom React hook.

#### Custom React Hook

Our custom hook `useRandomNumberEverySecond` generates a random number every second.

```javascript
function getRandomInt(max) {

return Math.floor(Math.random() * Math.floor(max));

}


function useRandomNumberEverySecond(max = 1000) {

const [number, setNumber] = useState(getRandomInt(max));

useEffect(() => {

const interval = setInterval(() => setNumber(getRandomInt(max)), 1000);

return () => clearInterval(interval);

}, [max]);

return number;

}
```

\n

#### The Main Component

Our main component looks like this, where `number` is provided by our custom hook (when active).

```javascript
export default function App() {

const [isHookActive, setIsHookActive] = useState(false);

const [number, setNumber] = useState(0);

return (



Bending the Rules of Hooks





{isHookActive ? `hook output is: ${number}` : "hook is not active"}



{isHookActive && }



);

}
```

Notice that the component `RandomNumberWrapper` only renders when `isHookActive` is true. Now let's take a look at `RandomNumberWrapper`.

Now let's see how our main component consumes the custom hook `useRandomNumberEverySecond`.

#### The Wrapper Component

```javascript
function RandomNumberWrapper({ setState }) {

const number = useRandomNumberEverySecond();

useEffect(() => {

setState(number);

}, [setState, number]);

return null;

}
```

And that's it! `RandomNumberWrapper` blindly proxies whatever data comes from `useRandomNumberEverySecond` via the callback `setState`, which then updates the `number` state property in our main component. You can go ahead and apply this pattern to any hook in your codebase, wrapping up, you need to:


1. Create a new component to **wrap the usage of the hook** you intent to use conditionally.
2. Pass into this new component, a `setter` that **allows you to forward the data** back to the parent component.
3. **Conditionally mount the new component** in your target component and pass in the `setter` as a prop to the new component, that's how you're going to receive the state updates coming from your custom React hook.

\
robot