리액트 훅
- 클래스 컴포넌트에서만 가능했던 state, ref 등 리액트의 핵심적인 기능을 함수에서도 가능하게 만듦
- 클래스 컴포넌트보다 간결하게 작성 가능
useState
- 함수 내부에서 상태를 정의하고, 이 상태를 관리할 수 있게 해주는 훅
- 인수로 사용할 state의 초깃값을 넘겨줌
- 반환 값은 배열이며, 배열의 첫 번째 원소로 state 값 자체를 사용할 수 있고, 두번째 원소인 setState 함수를 사용해 해당 state의 값을 변경할 수 있음
- 리액트는 클로저를 이용해 setState 함수의 실행이 종료된 이후에도 지역변수인 state를 계속 참조할 수 있게 함
게으른 초기화
- useState의 인수로 특정한 값을 넘기는 함수를 인수로 넣어줄 수 있음
- useState에 변수 대신 함수를 넘기는 것을 게으른 초기화라고 함
- useState의 초깃값이 복잡하거나 무거운 연산을 포함하고 있을 때 사용하라고 함
- 오로지 state가 처음 만들어질 때만 사용됨
const [counter, setCounter] = useState(() =>
Number.parseInt(window.localStorage.getItem(cacheKey)),
);
useEffect
- 애플리케이션 내 컴포넌트의 여러 값들을 활용해 동기적으로 부수 효과를 만드는 메커니즘
- 첫 번째 인수로는 실행할 부수 효과가 포함된 함수, 두 번째 인수는 의존성 배열을 전달
- 의존성 배열이 변경될 때마다 useEffect의 첫 번째 인수인 콜백이 실행됨
- 의존성 배열의 변경 여부는 단순히 렌더링할 때마다 의존성에 있는 값을 보면서 이전과 다르다면 부수 효과를 실행함
- state와 props의 변화 속에서 일어나는 렌더링 과정에서 실행되는 부수 효과 함수
클린업 함수
- 클린업 함수 : useEffect 내에서 반환되는 함수
- 이벤트를 등록하고 지울 때 사용해야 한다고 알려짐
- 클린업 함수는 새로운 값과 함께 렌더링된 뒤에 실행되지만 변경된 값을 읽지 않고 함수가 정의됐을 당시에 선언됐던 이전 값을 보고 실행됨
- 특정 이벤트 핸들러가 무한히 추가되는 것을 방지함
=> 왜지?
의존성 배열
- 보통 빈 배열을 두거나 아무런 값을 넘겨주지 않거나 사용자가 원하는 값을 넣어줄 수 있음
- 빈 배열이라면 useEffect는 비교할 의존성이 없다고 판단해 최초 렌더링 직후에 실행된 다음부터는 더 이상 실행되지 않음
- 아무런 값이 없다면 의존성을 비교할 필요 없이 렌더링할 때마다 실행이 필요하다고 판단해 렌더링이 발생할 때마다 실행됨
useEffect 사용 시 주의점
- eslint-disable-line react-hooks/exhaustive-deps 주석 자제할 것: useEffect는 반드시 의존성 배열로 전달한 값의 변경에 의해 실행돼야 하는 훅인데, 특히 빈배열로 두었을 때 부수 효과가 실제로 관찰해서 실행돼야 하는 값과는 별개로 작동함을 의미함
- useEffect의 첫 번째 인수에 함수명을 부여할 것 : 기명 함수로 바꾸는 것이 코드가 복잡하고 많아질수록 문제를 파악하기 쉬워짐
- 거대한 useEffect 만들지 말 것 : 적은 의존성 배열을 이용하는 여러 개의 useEffect로 분리할 것
- 불필요한 외부 함수 만들지 말 것
useMemo
- 비용이 큰 연산에 대한 결과를 저장해 두고, 이 저장된 값을 반환하는 훅
- 첫 번째 인수로는 어떤 값을 반환하는 생성 함수, 두 번째 인수로는 해당 함수가 의존하는 값의 배열을 전달함
- 렌더링 발생 시 의존성 배열의 값이 변경되지 않았으면 함수를 재실행하지 않고 이전에 기억해 둔 해당 값을 반환하고, 변경되었다면 첫 번째 인수의 함수를 실행한 후 그 값을 반환하고 기억할 것
- 메모이제이션은 컴포넌트도 가능함
useCallback
- useMemo가 값을 기억했다면, useCallback은 인수로 전달받은 콜백 자체를 기억함
- 첫 번째 인수로 함수를, 두 번째 인자로 의존성 배열을 넣으면 의존성 배열이 변경되지 않는 한 함수를 재생성하지 않음
- useMemo를 사용해 구현 가능함
useRef
- useState와 동일하게 컴포넌트 내부에서 렌더링이 일어나도 변경 가능한 상태값을 저장한다는 공통점
- 단, useRef는 반환값인 객체 내부에 있는 current 값에 접근 또는 변경 가능
- useRef는 그 값이 변하더라도 렌더링을 발생시키지 않음
- 렌더링에 영향을 미치지 않는 고정된 값을 관리하기 위해 사용
- DOM에 접근하고 싶을 때 사용
- 최초에 넘겨받은 기본값을 가짐
Context
- props drilling 문제를 극복하기 위해 나타난 개념이 바로 콘텍스트
- 명시적인 props 전달 없이도 선언한 하위 컴포넌트 모두에서 자유롭게 원하는 값 사용 가능
useContext
const Context = createContext<{hello : stirng} | undefined>(undefined)
function ParentComponent() {
<>
<Context.Provider value ={{hello : 'react'}}>
<Context.Provider value={{hello : 'javascript'}}>
<ChildComponent />
</Context.Provider>
</Context.Provider>
</>
}
function ChildComponent () {
const value = useContext(Context)
return <>{value ? value.hello : ''}</>
}
- 상위 컴포넌트에서 만들어진 Context를 함수 컴포넌트에서 사용할 수 있도록 만들어진 훅
- 상위 컴포넌트 어딘가에서 선언된 <Context.Provider />에서 제공한 값을 사용할 수 있음
- 여러 개의 Provider가 있다면 가장 가까운 Provider의 값을 가져오게 됨
- 하지만, 컴포넌트 트리가 복잡해질수록 콘텍스트를 사용하는 것도 만만치 않음
useContext 사용 시 주의점
- 함수 내부에서 사용할 때는 항상 컴포넌트의 재활용이 어려워진다는 점을 염두해야 함
- 컨택스트가 미치는 범위는 필요한 환경에서 최대한 좁게 만들어야 함
useReducer
- useState의 심화 버전
- 반환값은 useState와 동일하게 길이가 2인 배열
- state : 현재 useReducer가 가치고 있는 값
- dispatcher : state를 업데이트 하는 함수, setState롸 달리 값이 아닌 action을 넘겨줌
- 3개의 인수를 필요로 함
- reducer : useReducer의 기본 action을 정의하는 함수
- initialState : 초깃값
- init : 초깃값을 지연해서 생생시키고 싶을 때 사용하는 함수
- 복잡한 형태의 state를 사전에 정의된 dispatcher로만 수정할 수 있게 만들어 state 값에 대한 접근은 컴포넌트에서만 가능하게 하고, 이를 업데이트하는 방법에 대한 상세 정의는 컴포넌트 밖에 둔 다음, state의 업데이터를 미리 정의해 둔 dispatcher로만 제한하는 것
- 즉, state 값을 변경하는 시나리오를 제한적으로 두고 이에 대한 변경을 빠르게 확인할 수 있게 함
React.forwardRef
- ref 전달에 있어 일관성을 제공하기 위해 탄생함
useImperativeHandle
- 부모로부터 넘겨받은 ref를 원하는 대로 수정할 수 있는 훅
useLayoutEffect
- 모든 DOM 변경 후에 useLayoutEffect의 콜백 함수 실행이 동기적으로 발생함
- 실행 순서
- 리액트가 DOM 업데이트
- useLayoutEffect 실행
- 브라우저에 변경 사항 반영
- useEffect 실행
- DOM은 계산됐지만 이것이 화면에 반영되기 전에 하고 싶은 작업이 있을 때 사용
useDebugValue
- 일반적으로 프로덕션 웹서비스에서 사용되는 훅은 아님
- 리액트 애플리케이션을 개발하는 과정에서 사용
- 사용자 정의 훅 내부의 내용에 대한 정보를 남길 수 있는 훅
훅의 규칙
- 최상위에서만 훅을 호출해야 함. 반복문, 조건문, 중첩된 함수 내에서는 훅을 실행할 수 없음 => 컴포넌트가 렌더링될 때마다 항상 동일한 순서로 훅이 호출되는 것을 보장할 수 있음
- 훅을 호출할 수 있는 것은 리액트 함수 컴포넌트, 사용자 정의 훅 두 가지 경우
'FE > 리뷰' 카테고리의 다른 글
[모던 리액트 딥다이브] 4.1장 서버 사이드 렌더링 (0) | 2024.07.21 |
---|---|
[모던 리액트 딥다이브] 3.2장 사용자 정의 훅과 고차 컴포넌트 (0) | 2024.07.21 |
[모던 리액트 딥다이브] 2.5장 메모이제이션 (0) | 2024.07.13 |
[모던 리액트 딥다이브] 2.4장 렌더링 (0) | 2024.07.13 |
[모던 리액트 딥다이브] 2.3장 클래스 컴포넌트와 함수 컴포넌트 (0) | 2024.07.07 |