Skip to content

Commit 1cb02d3

Browse files
authored
React Deep Dive 스터디 2주차 3장
1 parent e321528 commit 1cb02d3

File tree

1 file changed

+79
-6
lines changed

1 file changed

+79
-6
lines changed

02/마님.md

+79-6
Original file line numberDiff line numberDiff line change
@@ -401,10 +401,20 @@ memo를 하지 않았을 때 발생할 수 있는 문제
401401
- 그리고 위 두 가지 모두가 모든 자식 컴포넌트에서 반복해서 일어남
402402
- 리액트가 구 트리와 신규 트리를 비교
403403
### 2.5.3 결론 및 정리
404+
404405
# 03. 리액트 훅 깊게 살펴보기
406+
함수형 컴폰넌트가 상태를 사용하거나 클래스형 컴포넌트의생명주기 메서드를 대체하는 등의 다양한 작업을 위해 hook 추가
405407
## 3.1 리액트의 모든 훅 파헤치기
406408
### 3.1.1 useState
407409
함수형 컴포넌트 내부에서 상태를 정의하고, 이 상태를 관리할 수 있게 해주는 훅
410+
411+
클로저를 이용하여 함수의 실행이 끝난 state에 접근하는 방식
412+
#### 게으른 초기화
413+
useState의 인수로 특정한 값을 넘기는 함수를 넣어줌
414+
415+
useState의 초깃값이 복잡하거나 무거운 연산을 포함하고 있을 때 사용 권장
416+
417+
최초 렌더링 이후에는 실행되지 않고 최초의 state 값을 넣을 때만 실행
408418
### 3.1.2 useEffect
409419
애플리케이션 내 컴포넌트의 여러 값들을 활용해 동기적으로 부수 효과를 만드는 매커니즘
410420
#### 클린업 함수의 목적
@@ -415,11 +425,13 @@ memo를 하지 않았을 때 발생할 수 있는 문제
415425
- useEffect는 클라이언트 사이드에서 실행되는 것을 보장하여 내부에서 window 객체의 접근에 의존하는 코드를 사용 가능
416426
- 컴포넌트가 렌더링되는 도중에 실행되는 직접 실행과 달리 컴포넌트의 렌더링이 완료된 이후에 실행(부수 효과)
417427
#### useEffect의 구현
428+
의존성 배열은 얕은 비교로 진행
418429
#### useEffect를 사용할 때 주의할 점
419430
- eslint-disable-line react-hooks/exhaustive-deps 주석은 최대한 자제하라
420-
- useEffect의 첫 번째 인수에 함수명을 부여하라
431+
- useEffect의 첫 번째 인수에 함수명을 부여하라(해당 useEffect의 목적을 파악하기 위해)
421432
- 거대한 useEffect를 만들지 마라
422433
- 불필요한 외부 함수를 만들지 마라
434+
- useEffect에서 비동기로 함수를 호출할 경우 경쟁 상태가 발생할 수 있어 콜백 함수로 넣을 수 없음, 내부에서 선언하거나 즉시 실행 비동기 함수를 만들어 사용 가능
423435
### 3.1.3 useMemo
424436
비용이 큰 연산에 대한 결과를 저장해 두고, 이 저장된 값을 반환하는 훅
425437

@@ -431,12 +443,29 @@ useState와 동일하게 컴포넌트 내부에서 렌더링이 일어나도 변
431443

432444
반환값인 객체 내부에 있는 current로 값에 접근 또는 변경할 수 있음
433445

434-
그 값이 변하더라도 렌더링을 하지 않음
446+
그 값이 변하더라도 렌더링을 하지 않음 // innerText에 useRef 객체의 current 값을 넣었을때, 값이 바뀌어도 리렌더링X
435447

436-
useRef는 컴포넌트가 렌더링될 때만 생성되며, 컴포넌트 인스턴스가 여러 개라도 각각 별개의 값을 바라봄
448+
useRef는 컴포넌트가 렌더링될 때만 생성되며, 컴포넌트 인스턴스가 여러 개라도 각각 별개의 값을 바라봄
449+
450+
컴포넌트가 최초로 렌더링될 때는 렌더링이 반환되기 전이므로 undefined이며, useEffect를 통해 렌더링 이후에 접근 가능
451+
452+
렌더링을 발생시키지 않고 원하는 상태값을 저장 가능
437453
### 3.1.6 useContext
454+
#### Context란?
455+
#### Context를 함수형 컴포넌트에서 사용할 수 있게 해주는 useContext 훅
456+
상위 컴포넌트에서 만들어진 Context를 함수형 컴포넌트에서 사용할 수 있도록 만들어진 훅
457+
458+
만약 여러 개의 Provider가 있다면 가장 가까운 Provider의 값을 가져옴
459+
460+
복잡해진다면 useContext 내부에서 해당 콘텍스트가 존재하는 환경인지 확인하여 에러를 방지할 수 있음
461+
438462
useContext는 Context.Provider를 통해 주입된 상태를 사용할 수 있을 뿐, 그 자체로는 렌더링 최적화에 도움이 되지 않음
463+
#### useContext를 사용할 때 주의할 점
464+
Provider에 의존성을 가지므로 재활용이 어려워짐
465+
466+
props로 전달하지 않더라도 전체가 리렌더링됨(단순 주입, 렌더링 최적화에는 도움이 되지 않음)
439467
### 3.1.7 useReducer
468+
useState와 비슷한 형태를 띠지만 좀 더 복잡한 상태값을 미리 정의해 놓은 시나리오에 따라 관리 가능
440469
```
441470
// useReducer가 사용할 state를 정의
442471
type State = {
@@ -500,9 +529,10 @@ export default function App() {
500529

501530
state 값을 변경하는 시나리오를 제한적으로 두고 이에 대한 변경을 빠르게 확인할 수 있게 하는 것이 목적
502531
### 3.1.8 useImperativeHandle
503-
#### forwardRef
532+
#### forwardRef 살펴보기
533+
ref가 예약어이기 때문에 props로 전달할 수 없는데, 이에 일관성을 제공하기 위해서 forward로 컴포넌트를 감싸 확실하게 ref를 전달하고 안전하게 받음
504534
```
505-
const ChildComponent = forwardRef((props, ref) => {
535+
const ChildComponent = forwardRef((props, ref) => { // 감싸기
506536
useEffect(() => {
507537
// { current: undefined }
508538
// { current: HTMLInputElement }
@@ -524,8 +554,41 @@ const ParentComponent() {
524554
}
525555
```
526556
ref를 받고자 하는 컴포넌트를 forwardRef로 감싸고, 두 번째 인수로 ref를 전달받은 후, 부모 컴포넌트에서는 동일하게 props.ref를 통해 ref를 넘겨줌
527-
#### useImperativeHandle
557+
#### useImperativeHandle이란?
528558
부모에게서 넘겨받은 ref를 원하는 대로 수정할 수 있는 훅
559+
```
560+
const Input = forwardRef((props, ref) => {
561+
useImperativeHandle(
562+
ref,
563+
() => ({
564+
alert: () => alert(props.value),
565+
}),
566+
[props.value],
567+
)
568+
569+
return <input ref={ref} {...props} />
570+
})
571+
572+
function App() {
573+
const inputRef = useRef();
574+
const [text, setText] = useState('');
575+
function handleClick() {
576+
inputRef.current.alert();
577+
}
578+
579+
function handleChange(e) {
580+
setText(e.target.value);
581+
}
582+
583+
return (
584+
<>
585+
<Input ref={inputRef} value={text} onChange={handleChange} />
586+
<button onClick={handleClick}>Focus</button>
587+
</>
588+
)
589+
}
590+
591+
```
529592
### 3.1.9 useLayoutEffect
530593
useEffect와 동일하나, 모든 DOM의 변경 후에 useLayoutEffect의 콜백함수 실행이 동기적으로 발생
531594
1. 리액트가 DOM을 업데이트
@@ -544,7 +607,17 @@ useEffect와 동일하나, 모든 DOM의 변경 후에 useLayoutEffect의 콜백
544607
## 3.2 사용자 정의 훅과 고차 컴포넌트 중 무엇을 써야 할까?
545608
### 3.2.1 사용자 정의 훅
546609
### 3.2.2 고차 컴포넌트
610+
#### React.memo란?
611+
리액트에서 제공하는 가장 유명한 고차 컴포넌트
612+
613+
state가 업데이트는 되지만 값은 같은 경우 React.memo를 통해서 변화 없음을 감지하여 이전에 기억한 컴포넌트를 그대로 반환
614+
547615
### 3.2.3 사용자 정의 훅과 고차 컴포넌트 중 무엇을 써야 할까?
616+
#### 사용자 정의 훅이 필요한 경우
617+
리액트에서 제공하는 훅으로만 공통 로직을 격리할 수 있는 경우 사용자 정의 훅 사용
618+
619+
고차 컴포넌트는 렌더링에 영향을 미치는 로직이 존재하므로 사용자 정의 훅에 비해 예측하기 어려움
620+
#### 고차 컴포넌트를 사용해야 하는 경우
548621
사용자 정의 훅은 그 자체로는 렌더링에 영향을 미치지 못하기 때문에 사용이 제한적이므로 반환하는 값을 바탕으로 무엇을 할지 설정 가능
549622

550623
렌더링의 결과물에도 영향을 미치는 공통 로직이라면 고차 컴포넌트를 사용

0 commit comments

Comments
 (0)