[Hook] 유저와의 UI 반응을 위한 상태관리 with Functional Components

2020. 5. 23. 16:46컴퓨터언어/React JS

728x90
반응형
UI = function (state)

 

물은 얼음과 같은 성분이지만, 온도에 따라 다른 상태를 가진다.

마찬가지로, React Component(ex. <App />)는 요소 자체는 그대로이지만, 상태를 담당하는 변수의 값에 따라 다른 UI를 가진다.

 

React에서 UI를 변경하는 데에는 Declarative Programming과 Imperative Programming 2가지 방식이 있다.

Declarative는 .jsx(js) 파일 상단에서 선언했던 상태 저장용 변수를, UI 변경을 담당하고자 만든 커스텀 함수의 body에서 변형시킴으로써(true->false처럼 toggle을 쓰는 등) 목적을 달성하는 방법이다.

Imperative는 document.querySelector 등으로 해당 HTML 요소에 접근하여 값을 직접 대입시키는 것이다.

 

그런데 단순히 ReactDOM.render()를 가지고 HTML을 렌더링했다면, UI 변경이 먹히지 않는다.

왜냐하면 일단 해당 .js파일이 로드되고 render()함수가 실행되면, 그것으로 한번의 렌더링은 이미 끝난 것이기 때문에 다시 Re-rendering이 되지 않는 한, 아무리 상태값을 바꾸려고 변수를 요리해봤자 적용이 되지 않는 것이다.

 

그렇다고 내가 만든 커스텀함수마다 ReactDOM.render()를 계속 추가하기에는 상당히 바람직하지 않다.

그래서 Hooks가 나온 것이다!


Hooks는 "react" 모듈 안의 useState() 함수를 사용한다.

(기존 class 기반의 상태관리에서는 this 키워드에 setState() 함수가 따로 있고, 바인딩까지 해야하는 등 굉장히 번거로웠지만,

Hooks는 함수 기반의 상태관리이므로 상당히 직관적이다.)

 

useState() 함수는 2개의 원소를 가진 배열을 반환한다.

첫번째 원소로는 개발자가 useState() 함수의 인자로 전달한 값이 들어가며, 이는 상태 초기값(바뀌기 전)을 저장한다.

그렇기 때문에 그 초기값을 사용하고 싶다면 배열의 첫째 인자이므로 다음과 같이 작성할 수 있다.

import React, {useState} from "react";

const state = useState(3.14);
console.log(state[0]) // 3.14

그런데 위와 같이 인덱스([0]) 형태로 코딩을 하다보면 나중에는 이게 무슨 값을 의미하는지 파악하기 어려울 수 있다.

따라서 다음과 같이 수정해주어야 한다. 즉 인덱싱을 숫자가 아닌, 개발자가 파악하기 쉬운 말로 바꾸어주는 것이다.

이렇게 배열이나 객체같이 복잡한 자료구조의 형태를 쉽게 변환하는 것을 Destructing이라고 한다.

import React, {useState} from "react";

const [state] = useState(3.14);
console.log(state) // 3.14

 

잠깐 생각해보자.

여기서 "초기값을 사용한다"는 것이 무슨 의미일까?

초기값이란 바뀌기 전을 뜻한다. 지금 우리는 상태의 변화에 따른 UI 변경을 원한다.

 

따라서 상태에 따라 유동적인 변화를 원한다면, 처음부터 HTML 요소를 작성할 때 위의 state 배열의 첫째 원소를 대입해주면 되는 것이다!


useState() 함수의 return값으로 나오는 배열의 두번째 원소로는 함수가 들어있다.

이 함수는 첫번째 원소로 들어있는 초기값에 (상태)변화를 주기 위한 핵심 기능으로, setter라고 불린다.

그리고 변화를 주는 방정식을 인자로 갖는다.

 

그리고 변화를 언제 줄지(setter를 언제 호출할 지) 결정하는 것은 개발자가 유저와의 상호작용을 위해 만든 <button>의 onClick이나 <input>의 onChange 등에서 작동되도록 설정할 수 있다.

이는 VanillaJS에서 addEventListener를 했듯이, ReactJS에서는 ReactDOM.render() 내부의 HTML 태그의 onClick 등 속성에 내가 정의한 함수를 state리스너로 등록하는 과정이다.

 

 

예를 들어 클릭이면 onClick, 값의 변화이면 onChange를 통해 state리스너를 호출하게 되고, 그 리스너 내부에서는 setter를 호출시키면 된다.

주의할 것은, 이 setter 내부에서는 state리스너 호출 시 전달된 event 인자를 사용할 수 없다.

728x90
반응형