Speaking Closures While Primitively Cloning React UseState Hook

Nora LC
Nerd For Tech
Published in
4 min readFeb 18, 2021

--

In this blog post, I am going to briefly define closure and showcase how React hook UseState works under the hood.

useState hook comes in very handy in a toggle button situation

So first what is a closure?

We can think about it just like MDN defines it as the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, closure is when a function is able to remember its lexical scope even when that function is executing outside its lexical scope.

The word “lexical” refers to the fact that lexical scoping uses the location where a variable is declared within the source code to determine where that variable is available. Nested functions have access to variables declared in their outer scope.

This is a simple example of closure from our browser console:

  • sayMyName() is initialized.
  • pikachu is created inside sayMyName().
  • pikachuYells() is initialized inside sayMyName().
  • alert(pikachu) is what we intend to have function pikachuYells() execute after we invoke it.
  • in order for it to execute, it needs to access the variable pikachu. Thanks to closure pikachu is remembered in the whole lexical scope of sayMyName().

result:

Just remember that the concept of closure is only more relevant when a function returns a function. The returned function has access to variables that are not in the global scope, but they solely exist in its closure.

I hope this clarified the fundamentals of closure. Now let’s talk about how useState was programmed using closure.

Why useState?

it is imperative to first import a function from React called useState.

import React, { useState } from "react";

useState hook lets us "hook into" React's internal state inside of our function component.

We are not going to get into so much details about the usages, but know that understanding closure and how this special function was built is very critical if you want to use React Hooks without having to worry as much about bugs.

Let’s start our primitive clone:

function useState(initialValue) {
var _val = initialValue
  • _val is a local variable created by useState.
function state() {
return _val
}
  • state is an inner function, a closure.
  • state() uses _val, declared by parent function.
function setState(newVal) {
_val = newVal
}
  • Setting _val without exposing _val.
return [state, setState]
}
  • Exposing functions for external use.
var [foo, setFoo] = useState(0)
  • Using array destructuring .

Here is the full code with some console.log’s to help us showcase the result:

function useState(initialValue) {
var _val = initialValue
function state() {
return _val
}
function setState(newVal) {
_val = newVal
}
return [state, setState]
}
var [foo, setFoo] = useState(0)
console.log(foo()) // logs 0 - the initialValue we gave
setFoo(1) // sets _val inside useState's scope
console.log(foo()) // logs 1 - new initialValue, despite exact same call

That was our primitive clone of React’s useState hook. In our function, there are 2 inner functions, state and setState. state returns a local variable _val defined above and setState sets the local variable to the parameter passed into it (i.e. newVal).

Like the above console.log’s made clear, we are able to access and manipulate (a.k.a. “close over”) the internal variable _val. They retain access to useState ‘s scope, and that reference is called closure. In the context of React and other frameworks, this looks like state, and that’s exactly what it is.

To conclude, I would like to share with you a very nifty process of thoughts, that I learned at Flatiron School.

As we now know, useState hook allows our data to be dynamic. Which means, anytime we don’t really need that force of change stimulation within our program, useState hook becomes useless. Therefore, here are the three questions to ask yourself before choosing to work with state:

  • Is the data passed in from a parent via props? If so, it probably isn’t state.
  • Does it remain unchanged over time? If so, it probably isn’t state.
  • Can you compute it based on any other state or props in your component? If so, it isn’t state.
Just me wishing the end of this article was instead the end of the global pandemic

--

--