불필요한 리렌더링 해결하기 :: useRef / react dev tools

1

리펙토링

목록 보기
4/5
post-thumbnail

🎀 문제 상황

textarea에 값을 입력할 때 useState로 저장하여 value로 넘겨주고 있다.
이때 리렌더링이 얼마나 자주 일어나는지 체크해보기 위해서 react dev tool로 확인해 보았다.

위 gif에서 확인되는 것 처럼
textarea에 글을 입력할 때 마다 렌더링이 되고 있음을 확인할 수 있다.

❗️렌더링이 되는 영역에 파란색 선으로 highlight가 되고 있고, 렌더링이 연속적으로 많이 되고 있다면 주황색으로 진해진다.

components/comment-write-box/index.tsx

const [commentValue, setCommentValue] = useState('');

...

<InputComment value={commentValue} setValue={setCommentValue} />

...

components/input/input-comment/index.tsx

const InputComment = ({ value, handleSubmit, setValue }: InputCommentProps) => {
  const handleChangeTextarea = (e: FormEvent<HTMLTextAreaElement>) => {
	setValue?.(e.currentTarget.value);
  };
  
  return (
    <StInputComment>
      ...
      <textarea value={value} onChange={handleChangeTextarea}></textarea>
      ...
    </StInputComment>
  );
};

textarea에 onChange가 발생할 때 마다
setState값을 변경시켜주고, 변경된 state값을
textarea의 value로 매번 넣어주고 있어서 렌더링이 발생하는 것이다.

🎀 useRef로 해결한다

useState와 달리 useRef는 변경된 값을 참조(저장)만 하고 있기 때문에 컴포넌트 리렌더링 시키지 않는다.

components/comment-write-box/index.tsx

const inputRef: LegacyRef<HTMLTextAreaElement> = useRef(null);

const uploadCommentMutation = useMutation({
  // react query 요청 보낼때 inputRef.current 값을 넣어 보낸다.
  mutationFn: () => postComment(inputRef.current?.value || '', idGroup.columnId, cardId, idGroup.dashboardId),
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['comments'] });
    if (inputRef.current) {
      inputRef.current.value = '';
    }
  },
});

...

<InputComment handleSubmit={handleSubmitComment} inputRef={inputRef} />

InputComment라는 자식 컴포넌트에 useRef 를 넘겨준다.

components/input/input-comment/index.tsx

interface InputCommentProps {
  defaultValue?: string;
  handleSubmit: (e: FormEvent<HTMLButtonElement>) => void;
  inputRef: LegacyRef<HTMLTextAreaElement> | undefined;
}

const InputComment = ({ defaultValue, inputRef, handleSubmit }: InputCommentProps) => {
  
  return (
    <StInputComment>
      ...
      <textarea ref={inputRef} onChange={handleChangeTextarea}></textarea>
      ...
    </StInputComment>
  );
};

onChange될 때 마다 setState 새로 하고 state값을 value에 넣어주는 것이 아니라
onChange된 값을 ref에 저장만 해두는 것으로 해결하였다.

이렇게 해주니 렌더링이 전혀 일어나고 있지 않다.

🎀 하지만 정말 이게 최선일까?

📌 페이지 마다 useRef가 필요해 ㅜㅜ

<InputComment handleSubmit={handleSubmitComment} inputRef={inputRef} />

inputComment라는 컴포넌트를 사용하는 모든 페이지에

const inputRef: LegacyRef<HTMLTextAreaElement> = useRef(null);

를 명시해 주어야 하는게 불편했다.

📌 react-hook-form 쓰면 쉽게 해결 됨

사실 로그인/ 회원가입 페이지는 react-hook-form을 이마 사용하고 있다.
라이브러리를 통하면 useRef 를 이용해서 손쉽게 리렌더링 문제 해결이 가능하다.

🎀 react dev tools에서 렌더링 확인하는 방법

혹시 설정 방법을 알고싶어하는 분들이 있을 수 있으니 추가 설명해 보겠당

react dev tool 우측 상단에 톱니바퀴 모양 아이콘을 누르면 설정창이 뜬다.
여기서 Highlight updates when components render를 활성화 시키자.
그럼 렌더링이 얼마나 자주 되고있는지 확인해 볼 수 있다 🤓

profile
일단 해. 그리고 잘 되면 잘 된 거, 잘 못되면 그냥 해본 거!

0개의 댓글