I'm About to Get You Hooked


Remember what React was like without hooks? When class components looked like “woke” OOP? (I don’t miss those days). You are probably familiar with react hooks but have you ever wondered how they work in the background? I mean, how does useState manage a components state? How does useContext manage the state of an area? How does useMemo memoize? Let’s go through what the guys at Facebook had in mind… I’ll go through the popular hooks and show you how they do the heavy lifting for you. This is the first article of a 3-part series. Today, we’ll go through the basic data structure of every hook before we get into specifics.
Prerequisites
Have a basic understanding of React and it’s hooks.
Get ready to have your mind blown.
A little background story
Hooks were introduced into react to help a component “reason” (stateful). A component without states is like a function without variables. Hooks keep track of these states and allow us to know when component needs updating depending on action triggers.
Wanna see something cool? You probably thought that a component is the smallest unit in React, noooppppeeee! Underneath the component is a more granular structure called a fibre. A fibre is associated with tasks carried out by different elements. For example, a fragment can help perform tasks on a list without adding a node to the React Tree, or a memo that keeps track of an element’s previous updates. The fibre will hold a memoized state of component until a change is triggered. Here is how that typically looks like.
The fibre here can only hold a single state instead of multiple. In the case that there are multiple states, they linked to each other using a linked list using the NEXT property. At the end of this linked list, the last hook is set to null. Let’s look at a fibre..
Any time you land on a page, react first calls an updateFunctionComponent()
which invokes a component and its props. When the component is mounting, updatingFiber()
and mountHook()
functions are called to check what hooks is associated with the current mount. Kinda much yeah? Let me break that down for you.
Updating function component
This functions simply invokes the components and its props. Here, the engine will check what elements exist and compares with what’s on screen. The difference is then committed. This is how the virtual DOM gets to update the real DOM.
let updatingFiber = ...
function updateFunctionComponent (Component, props) {
prevHook = null
let children = Component(props)
}
Mounting the hook
Now that we have successfully invoked the component and its props, let us mount the available hooks. We’ll first check if there is a previous hook, if there is no hook, we use the memoized hook as the point of entry into our linked list. If it exists, then we append it to the previous hook’s next property. If there are any updates made to the hooks, they are handled by updateHook()
.
function mountHook(){
const Hook ={
state: null
next: null
}
if(prevHook === null){
updatingFiber.memoizedState = Hook
prevHook = Hook
} else {
prevHook.next = Hook
prevHook = preHook.next
}
return Hook
}
// update hook once mounted
function updateHook(){
var Hook
if(prevHook === null){
Hook = updatingFiber.memoizedState
} else {
Hook = prevHook.next
}
prevHook = Hook
return Hook
}
Using the hook
Now that we have mounted and updated the hook into our component, how do we use it?… we useHook… hahaahahaa, see what I did? React’s engine has a _useHook()
that allows us to check the initial state of the hook in the fibre. The engine will first check if the component is mounted using an isFiberMounting
flag. The state under the mounted hook we discussed is then persisted throughout the component. It looks something like this:
function _useHook(initialState){
let Hook
if(isFiberMounting){
Hook = mountHook()
Hook.state= initialState
} else {
Hook = updateHook()
}
return Hook.state
}
That’s literally it. These four simple functions show us how a simple component successfully manages its states. We’ve mounted a component, a hook, and checked for its initial state. In your functional component, that typically looks like this: const Title = () => { const a = _useHook(0)}
. Familiar? What we can gather from this is, a hook is a function. It’ll typically take input arguments and return a value. Key points to note are:
Input arguments, though not all, can be used for a hook’s initial condition.
A hook can take zero or multiple arguments.
Not all hooks return a value.
The return value of a hook can be an input argument of another.
Hook Rules
Hooks’ Calling Order
You’ve probably heard that hooks can only be called at the top level of you functional component before any returns are made. Why would this be the case when they fit all characteristics of a normal javascript function? As we discussed earlier, hooks exist in a linked list, so they are naturally in a pre-existing order. Every time your component renders, the hooks will always be called in the same order. When the first hook is called, it’ll point to the second using the NEXT property and the link continues. That is why we are advised to avoid having hooks inside loops, conditions, or nested functions. Let me explain further why hooks cannot be in conditional statements.
Conditional Hook Issue
Let us build a component that returns different characters using a hook.
const Title =({flag})=> {
const a = flag? _useHook('a'):''
const b = _useHook('b')
return <h3> React Hooks + {a}{b}</h3>
}
When this component mounts it’ll listen to the stored states a and b in the different hooks. When the flag is false, we expect an empty string. On the first render if flag === true
then the values are assigned correctly. However, when flag is false, variable b will be set to char ‘a’. Why? When the flag === false
variable a
is skipped which changes the order of the hooks. variable b
shifts to read the memoized state under variable a
. Now imagine having multiple hooks… CHAOS!!!
To avoid this mess, you can call your conditional statements inside the hook or call the variables conditionally instead. Let us fix our code snippet.
const Title = ({flag}) =>{
const a = _useHook('a')
const b = _useHook('b')
const _a = flag ? a : ''
return <h3>React Hooks + {}{}</h3>
}
CHERRIIIOOOO….
Hope you learned something new today. You now know how a hook generally looks and how it works in the background. Now go forth and do great things. See you in the next one.
Subscribe to my newsletter
Read articles from Dame Techie directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Dame Techie
Dame Techie
Welcome to our tech blog! I'm Nyawira Muturi but you can call me Dame-Techie, a passionate technical writer dedicated to exploring the fascinating realms of JavaScript, React.js, and quality assurance. With a deep love for all things code and a commitment to delivering top-notch content, I strive to bring you the latest trends, best practices, and insightful tutorials that empower you to harness the true potential of these technologies. Whether you're a seasoned developer seeking advanced techniques or a beginner looking to kickstart your journey, our blog serves as your go-to resource. I believe in breaking down complex concepts into easy-to-understand language, making even the most intricate topics accessible to all.