Closures are a fundamental concept in JavaScript.
It’s a concept that is often asked about in technical interviews, and I remember memorizing it while preparing for my own technical interviews.
However, I didn’t quite understand how closures are used in practice, and I often pondered how to apply them effectively. This time, I want to study the concept of closures in more depth.
Problem
When passing a function as a parameter to customHook
, let’s observe how the state
value inside the function is output when the useCustom
component is unmounted.
import useCustom from './hooks/useCustom'
import { useState } from 'react'
export default function Home() {
const [state, setState] = useState(0)
useCustom(() => console.log('inner func state:', state))
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<div>{state}</div>
<button onClick={() => setState(state + 1)}>+</button>
</div>
)
}
import React, { useEffect } from 'react'
const useCustom = (func: Function, state: any) => {
console.log('params state:', state)
useEffect(() => {
return () => func()
}, [])
return <div>useCustom</div>
}
export default useCustom
Code Explanation
- On the initial render, the
state
is set to 0. - The
console.log
insideuseCustom
outputs the value ofstate
, which is the initial value of 0. - At this point, the
func
function passed touseCustom
also retains the state of 0 due to closures. When theuseCustom
component is unmounted, this function executes, but thestate
remains at 0. - Since the dependency array is empty, the
useEffect
runs only once, and it does not re-execute even if thestate
changes. - If you want to use the latest
state
value, you need to addstate
to the dependency array ofuseEffect
. Otherwise, due to closures, it will reference the previous state.