Javascript
를 배우다 보면 closure
를 배우게 되는데 막상 배우면 어떻게 사용해야 할지 어디에 사용되는지에 대해 감이 잘 안오게 됩니다. 그래서 우리가 흔히 사용하는 useState
를 통해서 어떤 식으로 사용 될 수 있는지 한 번 알아보겠습니다.
let val
function setState = (newVal) => {
val = newVal
}
function useState = (initVal) => {
const state = val || initVal // 리렌더링 되면서 바뀐값으로 수정.
return [state, setState]
}
이런 식으로 useState
를 간단하게 구현하면 다음과 같이 구현 할 수 있습니다. 하지만 이런 방식으로 구현하면 하나의 useState
밖에 쓸 수 없게 됩니다.
let hooks = [];
const React = (function () {
let cursor = 0;
return {
render(Component) {
const Comp = Component();
Comp.render();
cursor = 0; // 다음 렌더를 위해 초기화
console.log(hooks);
return Comp;
},
useState(initVal) {
hooks[cursor] = hooks[cursor] || initVal;
const setStateHookIndex = cursor; // setState의 클로저를 위해!
const setState = (newState) => (hooks[setStateHookIndex] = newState);
return [hooks[cursor++], setState];
},
};
})();
function Counter() {
const [count, setCount] = React.useState(0);
const [count2, setCount2] = React.useState(2);
return {
click: () => setCount(count + 1),
click2: () => setCount2(count2 + 1),
render: () => console.log("render", { count, count2 }),
};
}
여기서 Closuer
는 어디에 사용되었을까요? 바로 setStateHookIndex
가 클로저가 적용된 변수 라고 할 수 있습니다.
여기서 클로저를 사용되어야 하는 이유는 setState
내에서 cursor
바로 사용하면 cursor
값은 0으로 고정됩니다. 아마 useState 안에서 setState
를 처음 정의하는 과정에서 cursor
가 0으로 고정되어 사용되어지는 것으로 예상됩니다.