Skip to content

Commit 669acd2

Browse files
dangdang04
1 parent 2468a35 commit 669acd2

1 file changed

Lines changed: 146 additions & 0 deletions

File tree

chapter03/dangdang.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# 03장: 리액트 훅 깊게 살펴보기
2+
3+
리액트를 이루는 핵심 요소들을 깊게 살펴보고, 리액트의 렌더링 과정을 이해하는 장입니다.
4+
5+
<br>
6+
7+
- [03장: 리액트 훅 깊게 살펴보기](#03장-리액트-훅-깊게-살펴보기)
8+
- [3.1 리액트 훅 깊게 살펴보기](#31-리액트-훅-깊게-살펴보기)
9+
- [3.1.1 useState](#311-usestate)
10+
- [3.1.2 useEffect](#312-useeffect)
11+
- [3.1.3 useMemo](#313-usememo)
12+
- [3.1.4 useCallback](#314-usecallback)
13+
- [3.1.5 useRef](#315-useref)
14+
- [3.1.6 useContext](#316-usecontext)
15+
- [3.1.7 useReducer](#317-usereducer)
16+
- [3.1.8 useImperativeHandle](#318-useimperativehandle)
17+
- [3.1.9 useLayoutEffect](#319-uselayouteffect)
18+
- [3.1.10 useDebugValue](#3110-usedebugvalue)
19+
- [3.1.11 훅의 규칙](#3111-훅의-규칙)
20+
- [3.1.12 정리](#3112-정리)
21+
- [3.2 사용자 정의 훅과 고차 컴포넌트 중 무엇을 써야 할까?](#32-사용자-정의-훅과-고차-컴포넌트-중-무엇을-써야-할까)
22+
- [3.2.1 사용자 정의 훅](#321-사용자-정의-훅)
23+
- [3.2.2 고차 컴포넌트](#322-고차-컴포넌트)
24+
- [3.2.3 사용자 정의 훅과 고차 컴포넌트 중 무엇을 써야 할까?](#323-사용자-정의-훅과-고차-컴포넌트-중-무엇을-써야-할까)
25+
- [3.2.4 정리](#324-정리)
26+
27+
<br>
28+
29+
## 3.1 리액트 훅 깊게 살펴보기
30+
31+
### 3.1.1 useState
32+
- 렌더링에 사용할 변수와 그 변수를 변경하는 함수를 제공하는 훅
33+
```javascript
34+
const [state, setState] = useState(initialState)
35+
```
36+
- 변수에 직접 할당하지 않고 이런 훅을 사용하는 이유는?
37+
- 리액트에서 렌더링은 함수형 컴포넌트의 return과 클래스형 컴포넌트의 render 함수를 실행한 다음 이 실행 결과를 이전의 리액트 트리와 비교해 렌더링이 필요한 부분만 업데이트 하기 때문.
38+
- 즉, 변수에 할당하면 변경 사항이 생겨도 컴포넌트 리렌더링이 일어나지 않음.
39+
- 매번 렌더링이 발생할 때마다 함수는 다시 새롭게 실행된다.
40+
- setState 내부에서 state를 클로저를 이용해 유지한다.
41+
- 게으른 초기화
42+
- useState에 함수를 초기값으로 넣으면 한번만 실행해 할당하고 리렌더링시 함수는 무시된다.
43+
- 무거운 연산 등의 초기값을 함수로 사용함이 적합하다.
44+
45+
### 3.1.2 useEffect
46+
```javascript
47+
useEfect(() => {...}, [props, state]);
48+
```
49+
- 두 번째 인자로 전달하는 배열을 의존성 배열이라고 한다.
50+
- 의존성 배열에 변경이 일어나면 첫번째 전달 인자인 함수가 실행된다.
51+
- 의존성 배열에 빈 배열을 입력한 경우
52+
- 리액트는 이 useEffect는 비교할 의존성이 없다고 판단해 최초 렌더링 직후에 함수를 실행하고 그 이후에는 실행되지 않는다.
53+
- 의존성 배열에 암런 값도 전달하지 않는다면
54+
- 이 때는 의존성을 비교할 필요가 없다고 판단해 렌더링 할 때마다 실행된다.
55+
- useEffect에서 비동기 처리가 필요하다면 비동기 처리로 인한 경쟁상태를 방지하기 위해 동기 함수로 감싸서 처리한다.
56+
57+
### 3.1.3 useMemo
58+
- 비용이 큰 연산에 대한 결과를 저장해 두고 이 저장된 값을 반환하는 훅
59+
```javascript
60+
const memoizedValue = useMemo(() => expansiveComputation(a, b), [a, b]);
61+
```
62+
- 첫번째 인수로는 어떠한 값을 반환하는 생성함수를, 두 번째 인수로른 해당 함수가 의존하는 값의 배열을 전달
63+
- useMemo는 렌더링 발생 시 의존성 배열의 값이 변경되지 않았으면 함수를 재실행하지 않고, 이전에 기억해 둔 값을 반환하고, 의존성 배열의 값이 변경되었다면 첫번째 인수의 함수를 실행한 후에 그 값을 반환하고 그 값을 다시 기억해 둔다.
64+
- 단순히 값 뿐만 아니라 컴포넌트도 memoization 가능하다.
65+
- 의존성으로 선언된 값이 변하지 않는한 다시 수행되지 않으므로 무거운 연산에 사용이 적합
66+
67+
### 3.1.4 useCallback
68+
- 값의 메모이제이션을 위해 useMemo를 사용했다면, 함수의 메모이제이션을 위해 사용하는 것이 useCallback 훅
69+
- 첫번째 인수로 함수를, 두 번째 인수로 의존성 배열을 전달하면, useMemo와 마찬가지로 의존성 배열이 변경되지 않는 한 함수를 재생성하지 않는다.
70+
- useMemo와 useCallback의 유일한 차이는 메모이제이션하는 대상이 변수냐 함수냐일 뿐이다.
71+
72+
### 3.1.5 useRef
73+
- 컴포넌트가 렌더링 될 때만 생성되며, 컴포넌트 인스턴스가 여러개라도 각각 별개의 값을 바라본다.
74+
- useRef의 최초 기본값은 return 문에 정의해둔 DOM이 아니고 useRef()로 넘겨받은 인수이다.
75+
- 원하는 시점의 값을 렌더링에 영향을 미치지 않고 보관해 둘 때 사용
76+
- e.g.) usePrevious
77+
78+
### 3.1.6 useContext
79+
- 상태를 주입하는 기능
80+
- 자식 컴포넌트에 전달할 값을 외부에 정해두고 사용하는 방식
81+
```typescript
82+
const context = createContext<{hello:string} | undefined>()
83+
useContext(context)
84+
```
85+
- 유의점: useContext가 선언돼 있으면 provider에 의존성을 가지게 된다.
86+
87+
### 3.1.7 useReducer
88+
- useState 심화버전
89+
- state를 관리하는 것은 일반적으로 useState로도 충분하지만 state 하나가 가져야 할 값이 복잡하고 이를 수정하는 경우의 수가 많아진다면 state 관리가 어려워진다.
90+
- useReducer를 사용해 state를 관리하면 state를 사용하는 로직과 이를 관리하는 비지니스 로직을 분리할 수 있어 state를 관리하기가 한결 쉬워진다.
91+
- 반환값은 state와 state를 업데이트하는 함수이다. setState는 값을 넘겨주지만 여기서는 state를 변경할 수 있는 액션을 넘겨준다.
92+
- useState의 인수와 달리 2개에서 3개의 인수를 필요로한다. 첫번째 인수는 기본 액션, 두번째 인수는 초기값, 세번째 인수는 게으른 초기화를 사용할 때 사용되며, 선택적 인수이다. 세번째 인수인 함수는 두번째 인수를 인자로 사용한다.
93+
94+
### 3.1.8 useImperativeHandle
95+
- 부모에게서 넘겨받은 ref를 원하는대로 수정할 수 있는 훅
96+
- 원래 ref는 {current:<HTMLElement>}와 같은 형태로 HTMLElement만 주입할 수 있는 객체였다. 여기서는 전달받은 ref에다 useImperativeHandle 훅을 사용해 추가적인 동작을 정의했다. 이로써 부모는 단순히 HTMLElement 뿐만 아니라 자식 컴포넌트에서 새롭게 설정한 객체의 키와 값에 대해서도 접근할 수 있게 됐다.
97+
- useImperativeHandle을 사용하면 이 ref의 값에 원하는 값이나 액션을 정의할 수 있다.
98+
- forwardRef
99+
- ref를 전달하는데 있어서 일관성을 제공하기 위함
100+
- 자식 컴포넌트에 ref를 전달할 때 명확히 하여 개발에 편리함을 꾀하기 위함
101+
102+
103+
### 3.1.9 useLayoutEffect
104+
- useEffect와 동일하나 모든 DOM의 변경 후에 동기적으로 발생
105+
- useLayoutEffect가 useEffect보다 먼저 실행된다
106+
- useLayoutEffect는 브라우저에 변경사항이 반영되기 전에 실행되는 반면 useEffect는 브라우저에 변경사항이 반영된 이후에 실행된다.
107+
- 사용할 곳: DOM은 계산 됐지만 이것이 화면에 반영되기 전에 하고싶은 작업이 있을 때.
108+
109+
### 3.1.10 useDebugValue
110+
- 디버깅 하고 싶은 정보를 이 훅에다 사용하면 리액트 개발자 도구에서 볼 수 있다.
111+
- 사용자 정의 훅 내부의 내용에 대한 정보를 남길 수 있는 훅
112+
- 두번째 인수로 포매팅 함수를 전달하면 첫번째 인자 값이 변경됐을 때만 호출되어 포매팅된 값을 노출한다
113+
- 오직 다른 훅 내부에서만 실행할 수 있다.
114+
- 공통 훅을 제공하는 라이브러리나 대규모 웹 애플리케이션에서 디버깅 관련 정보를 제공하고 싶을 때 유용
115+
116+
### 3.1.11 훅의 규칙
117+
- 항상 훅은 실행 순서를 보장받을 수 있는 컴포넌트 최상단에 선언돼 있어야 한다. 조건문이필요하다면 반드시 훅 내부에서 수행해야 한다.
118+
119+
### 3.1.12 정리
120+
121+
<br>
122+
123+
## 3.2 사용자 정의 훅과 고차 컴포넌트 중 무엇을 써야 할까?
124+
125+
### 3.2.1 사용자 정의 훅
126+
- 서로 다른 컴포넌트 내부에서 같은 로직을 공유하고자 할 때 주로 사용
127+
- use로 시작하는 이름으로 만들어야 한다.
128+
- 복잡하고 반복되는 로직을 간단하게 만드는 용도
129+
- 내부에 다른 훅을 사용해 원하는 훅을 만드는 기법
130+
131+
132+
### 3.2.2 고차 컴포넌트
133+
- 고차함수와 동일하게 함수형 컴포넌트에서 다른 컴포넌트를 인자로 받아 컴포넌트를 반환하는 컴포넌트
134+
- 컴포넌트 전체를 감쌀 수 있다는 점에서 사용자 정의 훅보다 더욱 큰 영향력을 컴포넌트에 미칠 수 있다. 단순히 값을 반환하거나 부수 효과를 실행하는 사용자 정의 훅과는 다르게, 고차 컴포넌트는 컴포넌트의 결과물에 영향을 미칠 수 있는 다른 공통된 작업을 처리할 수 있다.
135+
- 사용자 정의 훅이 use로 시작하는 이름을 사용했다면 리액트의 고차 컴포넌트도 마찬가지로 with로 시작하는 이름을 사용해야한다.
136+
- props로 받은 컴포넌트를 임의로 수정, 추가, 삭제하지 않아야 한다.
137+
- 여러 개의 고차 컴포넌트로 컴포넌트를 감쌀 경우 복잡성이 커진다
138+
139+
### 3.2.3 사용자 정의 훅과 고차 컴포넌트 중 무엇을 써야 할까?
140+
- 사용자 정의 훅이 필요한 경우
141+
- 리액트에서 제공하는 훅으로만 공통 로직을 격리할 수 있을 때
142+
- 훅 자체로는 렌더링에 영향을 미치지 못하므로 개발자가 훅을 원하는 방향으로만 사용 가능
143+
- 고차 컴포넌트를 사용해야 하는 경우
144+
- 렌더링의 결과물에도 영향을 미치는 공통 로직
145+
146+
### 3.2.4 정리

0 commit comments

Comments
 (0)