1. useState
함수 컴포넌트 내부에서 상태를 정의하고, 이 상태를 관리할 수 있게 해주는 훅
아무런 값을 넘겨주지 않으면 초기값은 undefined
반환값은 배열, 첫 번째 원소로 state 값 자체를 사용하고 두 번째 원소인 setState함수를 통해 해당 state값 변경 가능
실제 리액트 코드에서는 useReducer로 표현되어 있음.
💫 useState를 사용하지 않고 상태값을 함수 내부에서 변수 사용해 관리하면 동작하지 않는 이유
: 리액트의 렌더링은 함수 컴포넌트의 반환 결과물인 return 의 값을 비교해서 실행.
리액트의 함수 컴포넌트는 렌더링될 때마다 함수가 다시 실행 되고, 그 때마다 함수 내부에서 선언된 변수들은 매번 새롭게 초기화 되므로 렌더링이 발생할 때마다 해당 변수가 초기화되어 이전 상태를 잃는 것.
💫 console.log(value); 와 console.log(value()); 결과가 다른 이유
: console.log(value)는 함수 자체를 출력, console.log(value()) 는 함수의 반환값을 출력
💫 리액트에서 클로저를 사용하는 이유
useState에 선언된 함수 setState가 함수 실행 종료된 후에도 state계속 참조할 수 있게 함.
💫 게으른 초기화
useState에서 원시값을 넣지 않고, 특정한 값을 넘기는 함수를 인수로 넣는 것
state가 처음 만들어질 때만 사용되고, 리렌더링이 발생되면 무시.
초깃값이 무거운 연산 또는 복잡한 값을 포함할 때 사용
ex. storage에 접근, 배열에 대한 접근, 초기값 계산 연산을 위해 함수 호출이 필요한 경우
2. useEffect
첫 번째 인수로 콜백(부수효과 발생할 함수), 두 번째 인수로 의존성 배열을 받고, 의존성 배열이 변경되면 콜백을 실행.
의존성 배열은 빈배열, 생략 모두 가능
💫 useEffect가 의존성 배열이 변경된 것을 알고 실행하는 원리
함수 컴포넌트는 매번 함수를 실행해 렌더링을 수행,
렌더링 할 때마다 의존성에 있는 값을 보며 의존성의 값이 전과 하나라도 다르면 부수효과를 실행
💫 클린업 함수
리액트는 컴포넌트가 업데이트될 때마다 useEffect를 다시 실행
-> 이전의 useEffect에서 설정한 것들을 제거하지 않으면 문제 발생 위험
1. 이벤트를 등록하고 지울때 사용
2. 비동기 작업을 취소할 때 사용
클린업 함수는 이전 state를 참조해 새로운 값과 함께 렌더링 된 후 실행
💫 useEffect에 이벤트를 추가했을 때 클린업 함수에서 지워야 하는 이유
컴포넌트가 계속해서 렌더링될 때마다 동일한 이벤트 리스너가 계속해서 추가되면, 동일한 이벤트에 대해 여러 핸들러가 중복해서 실행되는 문제가 발생
함수 컴포넌트 useEffect는 그 콜백이 실행될 때 마다 이전의 클린업 함수가 존재하면, 클린업 함수를 실행한 후 콜백을 실행함. 따라서 이벤트를 추가하기 전에 등록했던 이벤트 핸들러를 삭제하는 코드를 클린업 함수에 추가
-> 특정 이벤트 핸들러가 무한히 추가되는 것을 막을 수 있음
💫 의존성 배열
빈배열 : 최초 렌더링 직후에 실행되고 이후 실행되지 않음
아무것도 넘겨주지 않음 : 렌더링 할 때 마다 실행 -> 컴포넌트 렌더링 확인 용도
의존성 배열의 비교는 얕은 비교
💫 의존성 배열 주의
1. 의존성 배열을 넘기지 않은 채 콜백함수 내에서 특정 값을 사용하는 경우
2. 익명함수를 넘기는 것 -> 코드 추적이 어려워짐
3. 크기 -> 부수효과가 커질 수록 성능에 악영향
4. 불필요한 외부 함수 줄이기
+ 바로 비동기 함수 넣을 수 없는 이유 : 응답 속도에 영향 받기 때문,
하지만 즉시 실행 비동기함수나 useEffect 내부에서 선언한 비동기함수는 가능
-> 대신 클린업 함수에서 처리해주는 것을 추천
3. useMemo
비용이 큰 연산에 대한 결과를 저장하고 저장된 값 반환
첫 번째 인수는 어떤 값을 반환하는 함수, 두 번째 인수는 해당 함수가 의존하는 값의 배열
렌더링 발생 시, 의존성 배열 값 변경되었을 경우에만 첫 번째 인수의 함수 실행하고, 값을 반환해 기억.
의존성 배열 값 변경 안되었으면 함수 재실행 x, 이전에 기억한 값 반환
값 뿐만 아니라 컴포넌트도 감쌀 수 있음, 하지만, 컴포넌트는 React.Memo 사용이 더 효과적.
💫 React.memo와 useMemo 차이?
- React.memo는 컴포넌트의 불필요한 렌더링 방지가 목적,
부모 컴포넌트가 다시 렌더링될 때마다 자식 컴포넌트도 다시 렌더링되는데,
React.memo를 사용하면, 컴포넌트의 props가 이전 렌더링과 비교하여 변하지 않았을 경우, 그 컴포넌트를 다시 렌더링하지 않음.
- useMemo는 복잡한 계산의 결과를 메모이제이션 -> 불필요한 재계산을 방지하는 것이 목적,
함수 컴포넌트 내에서 특정 의존성 배열에 있는 값들이 변경되지 않는 한, 이전에 계산된 결과를 반환
💫 useMemo를 통해 컴포넌트 메모이제이션 하는 것과 React.memo 사용의 차이?
- useMemo는 컴포넌트의 반환값(JSX)을 메모이제이션
계산된 값이나 JSX 요소가 다시 계산되지 않도록.
-> 특정 의존성이 변경되지 않는 한, 리액트가 이전에 계산된 JSX를 재사용
- React.memo는 컴포넌트 자체를 메모이제이션
부모 컴포넌트가 다시 렌더링되더라도 props가 변경되지 않으면 해당 컴포넌트는 다시 렌더링되지 않음.
-> 전체 컴포넌트의 렌더링을 최적화
💫 useMemo를 써도 자식 컴포넌트가 렌더링 되는 이유?
: 리렌더링 될 때 함수가 재생성되기 때문.-> useCallback 사용해주기
4. useCallback
인수로 넘겨받은 콜백 자체를기억 해서, 함수를 새로 만들지 않고 다시 재사용
첫 번째 인수는 함수, 두 번째 인수는 해당 함수가 의존성 배열
의존성 배열 값 변경 안되었으면 함수 재생성 x
useMemo로 구현 가능(반환문으로 함수 선언문을 반환)
💫 useMemo와 useCallback 차이?
: 메모이제이션 하는 대상이 다름.
useMemo는 변수를 기억, useCallback는 함수를 기억
'스터디 > 모던 리액트 Deep Dive(24.07-24.10)' 카테고리의 다른 글
3.3 : 리액트 훅 (훅의 규칙, 사용자 정의 훅, 고차 컴포넌트) (1) | 2024.08.27 |
---|---|
3.2 : 리액트 훅 (useRef, useContext, useReducer, useLayoutEffect,...) (0) | 2024.08.27 |
2.4-2.5 : 리액트 핵심 요소 (렌더링, 메모이제이션) (0) | 2024.08.19 |
2.1-2.3 : 리액트 핵심 요소 (JSX, 가상DOM, 리액트 파이버, 클래스/함수 컴포넌트) (0) | 2024.08.19 |
1 : 자바스크립트 문법 (0) | 2024.08.05 |