이 글은 useState를 사용하는 방법이나,
어떻게 하면 더 효율적으로 사용 할 수 있는지에 대한 how to와 관련된 글이 아님을 밝힙니다.
이 글의 목적은
대략적으로 설명해보고자 합니다. 아주 추상화해서 설명할 예정이니 실제로 이렇게 동작한다기보다, 이런 컨셉(?)으로 동작하는구나 정도로만 이해해주세요.
아주 기초적인 내용이라 리액트를 처음 접하시는 분이 대상입니다!!
아주아주 간단한 예시입니다.
이 코드를 실행하고, div태그를 두 번 클릭하면 console.log가 어떻게 찍힐지 예상하실 수 있나요?
(있다면 뒤로가기를....)
(못생긴 예시 ㅎㅎ..)
첫 번째 클릭에서 click!!이 기록되고, 두 번째 클릭에서 '실행될까??'가 기록되었습니다.
혹시 첫 번째 클릭부터 '실행될까??'가 콘솔에 기록될거라 생각하신분이 계시다면, 이 글을 계속 읽어주세요.
(아니라면.. 뒤로가기를....)
이 글을 쓰게 된 이유가 바로 이 지점입니다.
아시다시피 useState는 배열을 반환하며,
우리는 이 배열을 비구조화 할당을 통해 이렇게 뽑아 사용하죠.
const [state, setState] = useState(initiailState)
하지만 간혹, 이 setState가 state를 변경시킨다고 오해하시는 분들이 있는거 같아서 이 글을 작성하게 되었습니다! (TIL만 가득한 블로그 포스팅도 할겸..).
생각해보세요, 우리는 state를 const로 선언했습니다. 값이 변할리 없죠!😎😎
그럼 useState가 내부적으로 어떻게 동작하는지, 우리는 어떻게 변경된 상태값을 컨트롤하며 컴포넌트를 리렌더링 하는지 알아봅시다.
(이 부분은 적당히 보고 넘어가세요!)
import {useState} from 'react'
먼저 import 문부터 살펴보죠.
우리는 'react'라는 모듈에서 useState를 named import해서 사용하고 있습니다.
위 사진은 node_modules/react/cjs/react.development.js 내부에 각종 hooks 함수가 선언된 곳입니다. useState는 dispatcher라는 인스턴스를 생성하고, 인자로 초기값을 받아 dispatcher.useState에 전달후 반환값을 return합니다. 즉
뒤에서 더 간단하게 정리해볼 예정이니 일단 그런가보다 하고 넘어가겠습니다.
더 거슬러 올라가서 dispatcher를 반환하는 resolveDispatcher 함수를 찾아보죠.
이 함수는 어디선가 dispatcher를 가져오고 에러처리를 하네요.
새로운 키워드로 ReactCurrentDispatcher가 나왔습니다. 좀 더 거슬러 올라가보겠습니다. 🐋
자, 이제 다왔습니다. ReactCurrentDispatcher라는 객체는 전역에 선언된 녀석이고, 속성으로 current를 가지고 있네요. 이 current가 우리가 찾던 dispatcher가 담길 곳입니다. 언제 어떻게 dispatcher가 담기는지는 넘어가겠습니다. 여기서 더 깊게 들어가면 리액트를 아예 뜯는 사태가 벌어질테니..
뭔가 떠오르지 않나요? 함수가 선언부보다 상위에 있는 값에 접근하는 것... 바로 Closure입니다.
혹시 이 과정을 더 자세히 알고 싶으시다면 이 글을 추천드립니다.
React 톺아보기 - 03. Hooks_1
다시 처음에 작성한 예시와, 아주아주 간단하게 작성한 react 모듈 코드를 예로 들겠습니다.
App 컴포넌트 함수는 실행되면 먼저 useState를 호출해서 반환값을 비구조화 할당으로 추출해 변수에 저장합니다.
여기서 중요한건, App도 함수라는 겁니다. jsx를 반환하는 함수일뿐이죠. 렌더링이 시작되면 이 함수가 호출되어 새로운 jsx을 반환합니다.
우측의 react 모듈 코드를 보면, useState 밖에 전역으로 선언된 _value가 있습니다. 우리가 useState를 통해 관리하는 '상태'는 바로 이녀석입니다. setState는 App함수에 선언된 state가 아니라, 자신이 선언된 위치에서 접근할 수 있는 _value를 변경합니다! 이는 closure의 개념을 알면 바로 이해할 수 있으리라 생각합니다.
위에서 리렌더링 과정에서 해당 컴포넌트 함수가 실행되고, 새로운 jsx를 반환한다고 정리했습니다.
setState가 리렌더링을 트리거하며 App함수가 두 번째로 실행되었을 때
즉, setState 함수는 자신과 함께 반환된 변수를 변경시키는게 아니라(const!!), 다음 useState가 반환할 react 모듈의 _value를 변경시키고, 컴포넌트를 리렌더링 시키는 역할을 합니다. 변경된 값은 useState가 가져옵니다!
이후 두 번째 리렌더링(세번째 App함수 실행)이 일어나겠지만, 생략하겠습니다!
setState를 쓴 앞뒤의 state를 출력해봤는데, 같은 값이 나오길래 찾아왔습니다!
알기 쉽게 설명해주셔서 감사합니다 :) 공부 더 열심히 해야겠네요;;
setState 는 state를 다음번에 렌더링 될 state를 set 할 뿐,
현재 렌더링 시점에서의 state를 변경시켜주지는 않는다는 걸까요??
글 너무 잘 읽었습니다.