React는 상태(props, state)가 변경될 때 re-render 한다.
useState
로 설정된 내부 상태가 변경 될 때, component 전체를 다시 호출한다.
virtual DOM과 비교해서 실제 변경된 부분만 DOM Tree에 업데이트 한다.
useState
는 여러번 호출되어도, state 값을 기억한다.
useEffect
는 기본적으로 컴포넌트 렌더링과 동일하게, DOM이 업데이트 될 때마다 특정 함수를 실행할 수 있다.
1) 컴포넌트가 마운트 됐을 때 (처음 렌더링 될 때), 2) 언마운트 됐을 때 (사라질 때), 3) 특정 상태가 업데이트 될 때 작업을 처리할 수 있게 해주는 React Hook이다.
state 업데이트 하는 로직을 컴포넌트에서 분리할 수 있다.
[React Docs] Scaling Up with Reducer and Context
원래 useState
를 사용하면 참조 값이 변해야 업데이트를 감지한다.
따라서 배열에 단순히 push, pop 등 메서드를 사용하는 것으로는 배열 참조값이 바뀌지 않아 state가 업데이트 되지 않는다.
Immer
라는 외부 라이브러리를 사용하면 state 업데이트 시 배열, 객체를 새로 반환하는 로직을 대신 해준다.
그러면 push 등 메서드를 사용 가능할 수 있어 깔끔해진다.
Introduction to Immer
하위 컴포넌트에서 상위 컴포넌트의 상태를 사용하기 위해서는 Prop Drilling
으로 상태를 계속 넘겨주어야 한다.
언어, 테마, 로그인 등 전역에서 관리되어야 하는 상태라면? 상위 컴포넌트에서 상태가 변경될 때마다 최하위까지 Prop Drilling 된다.
상태를 관리하기 편하게 도와주는 것이 Context API
이다.
필요한 곳에 Wrapper로 씌워주면 중간 컴포넌트에 불필요한 props를 넘기지 않아도 상태를 사용할 수 있다.
Context를 전역에서 사용할 수도 있지만, 적당한 상위 컴포넌트에 사용하는 것이 좋다.
UI 컴포넌트의 리렌더링을 방지해서 성능을 최적화 한다.
React는 컴포넌트 상태가 변경되면 항상 함수가 다시 호출된다.
함수가 다시 호출되더라도 props 값이 같다면 React.memo
로 컴포넌트 함수를 감싸서 re-render를 방지할 수 있다.
하지만!!! props 값에 함수나 객체가 할당되면, 호출 될 때마다 항상 새로운 변수로 할당되어서 전달되기 때문에 값이 같더라도 참조값이 달라질 수 있다. → re-render 된다. ⇒ useMemo
사용!!
const MyComponent = React.memo(function MyComponent(props) {
/* props를 사용하여 렌더링 */
});
React.memo
와 달리 컴포넌트 내부에서 호출하는 함수이다.
콜백함수의 결과로 반환된 값을 기억한다.
의존성 deps 값이 있을 경우 그 값이 변경되었을 때만 함수가 다시 호출된다.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
콜백 함수로 전달되는 함수 자체를 기억한다.
의존성이 있을 경우 deps가 변하면 새로운 함수를 리턴한다. (함수 재생성 방지)
const memoizedCallback = useCallback(() =>
{
doSomething(a, b);
},
[a, b],
);