[TIL] 1/30 React 숙련주차(2) hooks
useRef
useState와 더불어서 값을 저장하는데 쓰는 대표적인 react훅
rendering과 상관없이 값을 저장하고 싶을 때 쓴다
돔요소를 핸들링하기 위해서도 많이 사용
useState는 렌더링을 일으킬 수 있지만 useRef는 렌더링을 일으키지 않는다
useContext
나중에 redux 배울 때 가장 중요하게 참조될 개념!
1. react context의 필요성
일반적으로 부모 컴포넌트 -> 자식 컴포넌트로 데이터를 전달해 줄 때 props를 사용했다
하지만 이게 너무 깊어지면 prop drilling 현상이 일어난다
prop drilling의 문제점
1. 깊이가 너무 깊어지면 이 prop이 어떤 컴포넌트에서 왔는지 파악이 어려워진다
2. 어떤 컴포넌트에서 오류가 발생할 경우 추적이 힘들어진다 -> 대처가 늦어진다
useContext는 어떤 영역 안에서 모두가 데이터를 공유하게 되어 drilling 문제를 조금 해소할 수 있게 된다
-> 전역 데이터를 관리 할 수 있게 됨
2. context API 필수 개념
- createContext : context를 생성한다
- useContext : context를 구독하고 해당 context의 현재 값을 읽는다
- Provider : context를 하위 컴포넌트에게 전달한다(제공한다)
context의 문제점
provider에서 제공하는 value값이 달라지면 그 값을 참조하는 모든 부분이 리렌더링이 일어난다
memoization
1. 리렌더링의 발생 조건
1) 컴포넌트에서 state가 바뀌었을 때
2) 컴포넌트가 내려받은 props가 변경되었을 때
3) 부모 컴포넌트가 리렌더링 된 경우 자식 컴포넌트는 모두 리렌더링
2. 최적화
리엑트에서 리렌더링이 자주 일어나는 것 = 비용이 많이 발생하는 것 -> 최대한 줄여야 함 = 최적화
최적화 방법
1) memo(React.memo): 컴포넌트를 캐싱
2) useCallback: 함수를 캐싱
3) useMemo: 값을 캐싱
즉, 임시 값을 저장해두고 그걸 가져다 쓰는 것
memo
컴포넌트를 memoization하는 방법
부모 컴포넌트가 리렌더링 돼서 자녀 컴포넌트가 리렌더링되면 자녀 컴포넌트 입장에서는 바뀐게 없는데 왜 리렌더링 되야 하지? 하는 것
그것을 돕는 도구 : React.memo()
export 할 때 React.memo()로 감싸서 컴포넌트를 캐싱한다
export default React.memo(000);
useCallback
함수자체를 기억한다
memo로 감싸줘도 App.jsx에서 함수를 내려받았을 때 그 함수를 실행해서 값이 변경되면 해당 컴포넌트는 리렌더링이 일어난다
=> 함수형 컴포넌트를 사용하기 때문이다
부모 컴포넌트가 리렌더링되면서 함수가 다시 생성되어 함수를 참조하는 주소값이 변경됨
= 함수를 참조하는 컴포넌트의 내용이 변경되었기 때문에 해당 컴포넌트가 리렌더링 되는 것
=> 해당 함수를 메모리 공간에 저장을 해두고(주소값을 저장) 특정 조건이 아니면 변경 되지 않게 하는게 중요하다
함수를 useCallBack()으로 감싸고 의존성배열을 넣어 조건을 걸 수 있게 한다
const 000 = callBack(() => {},[])
useMemo
무거운 작업을 하는 함수의 값을 캐싱한다
함수가 리렌더링이 일어날 때마다 실행되면 느려지니까 필요할 때만 실행되도록 useMemo로 감싸준다
const 000 = useMemo(() => 값을 캐싱할 콜백 함수(), []);
하지만 모든 것들을 캐싱처리하면 캐싱처리한 값들을 별도로 저장해야하기 때문에 오히려 성능이 떨어질 수 있으니.
필요할 때에만 캐싱처리하자
custom hooks
custom hooks을 만들 때 주의사항
1. custom hook의 함수 이름은 use로 시작하는 것이 좋다 (useInput)
2. 파일 이름은 원하는 대로 (useInput)
input태그를 만들 때마다 넣어야 하는 함수를 따로 빼서 일반화 시킴으로 코드를 간결하게 사용할 수 있게 됐다