Breaking Down React Hooks (part 1)
Tags: react
Published: 2024-03-07 02:41:40

I wanted to learn more about how React Hooks work under the hook, so I dove in the source code. In this blog we'll demistify all hooks and learn a bit about typed Javascript and React. Let's go!


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/904012m9iunimyvq6cky.jpg)



## useState


Let's start with React's most used hook

```
const [count, setCount] = useState(0);
```

The first thing we notice is the "[var, setVar]" syntax. This is actually Javascript syntax that allows you to spread an array returned from a function. Check example below.

```
function fn() {
  let var1 = 'Hello', var2 = 'World', var3 = '!';
  return [var1, var2, var3];
}

const [var1, var2, var3] = fn();
console.log(var1); // Outputs: Hello
console.log(var2); // Outputs: World
console.log(var3); // Outputs: !
```

---


Anyway, let's look at the useState source code.


```
export function useState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
  const dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}
```


That's the whole code for the useState function! It looks like Typescript, but actually Flow is used for types, originally developed at Facebook.


Looking again at how state is initialized

```
const [count, setCount] = useState(0);
```

We see that we pass a generic value "0" which could be a number, string or even a function that returns a value. How do I know this? It's in the source!


```
function useState<S>(
  initialState: (() => S) | S,
)
```

Here we get that a generic value is passed (research Generics if you don't know this concept) and it can be the generic value itself or a function.

Let's look further.


```
[S, Dispatch<BasicStateAction<S>>] 
```

We also get that the return type is an array with 2 values, S (generic vlaue) and a Dispatch function that helps use update that state. This is what we broke down initially, remember?


We won't go into what a dispatcher is, yet. It's a very important concept but I'm already making this too long.
Basically it "dispatches" a change of state through a "reducer".


## useEffect

```
export function useEffect(
  create: () => (() => void) | void,
  deps: Array<mixed> | void | null,
): void {
  const dispatcher = resolveDispatcher();
  return dispatcher.useEffect(create, deps);
}
```

That is the whole code for useEffect. Yes, I know! It's short.

We can see almost the same format as in useState. But this time we take a function and an array as arguments. The function itself returns either another function or void.


If you look at an example of useEffect:

```
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  }, []);
```

We precisely see that useEffect() takes first a function as argument, and then an optional array.

In typescript you'd see the use of "?:" for optional types but here we see this which works for Flow:

```
 deps: Array<mixed> | void | null,
```

We also see the use of dispatchers again and a dispatcher being called with "dispatcher.useEffect". Let me know if you want me to go more in depth on the dispatchers in a later blog.

## More hooks

Let's see more hook examples

```
export function useContext<T>(Context: ReactContext<T>): T {
  const dispatcher = resolveDispatcher();
  return dispatcher.useContext(Context);
}
```

```
export function useReducer<S, I, A>(
  reducer: (S, A) => S,
  initialArg: I,
  init?: I => S,
): [S, Dispatch<A>] {
  const dispatcher = resolveDispatcher();
  return dispatcher.useReducer(reducer, initialArg, init);
}
```

```
export function useCallback<T>(
  callback: T,
  deps: Array<mixed> | void | null,
): T {
  const dispatcher = resolveDispatcher();
  return dispatcher.useCallback(callback, deps);
}
```


Now we notice that we can no longer avoid this anymore, we must know what a dispatcher is!


If you're interested, we'll continue in part 2.