Context API 와 useMemo warning

이동현·2022년 5월 15일
0

React

목록 보기
12/16

상황

다양한 컴포넌트로 이루어진 제어컴포넌트에서 prop drilling이 발생하고 있었고 이를 해결하기 위해서 제어 컴포넌트 내에서 context API 를 활용해서 이 문제를 해결하려고 했다.

예를 들어, AddCard 컴포넌트 하위의 CardForm 컴포넌트가 있고 그 하위에 CardNumberInput 컴포넌트가 있고 또 하위에 Input 컴포넌트가 있는 상황을 생각해보자.

input 값으로 사용자의 입력이 들어오면 제어 컴포넌트 중 가장 상위에 있는 AddCard 가 갖고 있는 card state를 업데이트 해줘야 한다.

Context API 를 사용하지 않았을 때는 updateCard 라는 state를 변경해주는 함수를 모든 컴포넌트가 props로 가져야 했다. 실제로 CardForm, CardNumberInput 컴포넌트에서는 prop을 넘겨주기만 할 뿐 사용하지 않기 때문에 불필요한 prop을 갖고 있게 되는 것이다.

문제

위와 같은 상황에서 제어 컴포넌트 안에서만 공유되는 객체를 관리하기 위해서 Context API를 사용했다.

그런데 현재 Context 가 앱의 최상위 컴포넌트에서 전역으로 사용되는 것이 아니라 앱의 일부인 제어 컴포넌트의 범주 안에서만 공유되는 객체로 사용되고 있다.

AddCard.jsx

function AddCard() {
  const [card, setCard] = useState(getCard());

  const updateCard = (name, value) => {
    setCard((prevCard) => {
      return { ...prevCard, [name]: value };
    });
  };
  ...

  return (
    <AddCardContext.Provider value={card, updateCard}>
      <h2 className="page-title">카드 추가</h2>
      <Card />
      <AddCardForm />
    </AddCardContext.Provider>
  );
}
...

그래서 Context를 선언하고 있는 AddCard 컴포넌트에서 context Provider를 통해서 value를 제공하고 있다. 해당 컴포넌트가 상위의 state 변화에 따라 리렌더링 될 때 위와 같이 value에 객체나 배열 등의 형태로 넘겨주게 되면 컴포넌트가 리렌더링 될 때 매번 새로운 객체를 생성해서 비교 알고리즘에 의해 다른 값이라고 생각해서 context를 구독하는 하위의 컴포넌트가 값이 변경되지 않았음에도 불구하고 다시 렌더링 되는 문제가 생긴다.

그렇기 때문에 useMemo 훅을 사용하라는 warning을 주게 되고 이 문제를 해결하기 위해서 useMemo 훅을 사용했다.

해결

위 코드에서 useMemo 훅만 추가를 해주면 의미없이 리렌더링되는 부분을 최적화할 수 있다.

AddCard 컴포넌트 안에 아래 코드를 추가하고 value 값에 넣어줌으로써 문제를 해결했다.

const contextValue = useMemo(() => ({ card, updateCard }), [card]);

...

  return (
    <AddCardContext.Provider value={contextValue}>
      <Card />
      <AddCardForm />
    </AddCardContext.Provider>
  );

이렇게 하면 값이 변경될때만 하위 컴포넌트들을 리렌더링 하기 때문에 최적화 달성이 가능해진다.

출처

useMemo inside context
StackOverflow - is useMemo required to manage state via the context API in reactjs?

profile
Dom Hardy : 멋쟁이 개발자 되기 인생 프로젝트 진행중

0개의 댓글