본문 바로가기

개발 공부

[React] useEffect()를 제거해보자!

effect를 제거했을 때 이점

코드를 더 쉽게 따라갈 수 있고, 실행 속도가 빨라지며, 오류 발생 가능성이 줄어든다.

불필요한 Effect를 제거하는 방법

1. 렌더링을 위해 데이터를 변환하는 경우

- 렌더링 과정: React는 먼저 컴포넌트 함수를 호출해 화면에 표시될 내용을 계산한다 -> 화면 업데이트 -> Effect 실행

- Effect를 이용하여 state를 즉시 업데이트 한다면, 전체 프로세스가 처음부터 다시 시작된다.

- 즉, 불필요한 렌더링이 발생한다. 

- 해결법: 데이터 변환을 컴포넌트 최상위 레벨에서 진행하면, props나 state가 변경될 때 해당 코드가 다시 실행된다.

 

2. 사용자 이벤트를 처리하는 경우

- 이벤트 핸들러를 제작할 경우 어떤 일이 일어나는지 정확하게 알 수 있지만, Effect를 이용할 경우 사용자가 어떤 일을 했는지 파악할 수 없습니다.

//저장 버튼을 클릭했을 때,저장되는 이벤트 핸들러
const handleSaveUser = () => {}

// user가 바뀌면 자동으로 저장되는 useEffect
useEffect(()=>{},[user])

 

props 또는 state에 따라 state 업데이트하기

1. 기존 props나 state에서 계산할 수 있는 것은 state를 사용하지 말자.

- 이점: 코드가 더 빨라지고(추가적인 '계단식' 업데이트를 피함), 더 간단해지고(일부 코드 제거), 오류가 덜 발생한다.(서로 다른 state 변수가 서로 동기화 되지 않아 발생하는 버그를 피함)

//좋은 코드
const [koreaName,setKoreaName] = useState('워터');
const [englishName,setEnglishName] = useState('water');

const nickname = koreaName + '(' + englishName + ')';

 

고비용 계산 캐싱하기(1초 이상이 걸린다면)

- 데이터가 많을 경우, 다시 계산하고 싶지않을 때는 useMemo 훅으로 감싸서 캐시를 사용하면된다.

- useMemoㄹ르 사용하게 될 경우 [ ]에 들어있는 해당 값이 변경되지 않는다면 내부 함수가 다시 실행되지 않는다.

 - 렌더링 과정: getFilterTodos() 반환값을 기억 -> 렌더링 중 [ ]에 들어있는 해당 값이 다른지 확인 -> 같다면 저장한 결과 반환 -> 다르면 내부함수 다시 호출 -> 저장

import { useMemo, useState } from 'react';

function TodoList({ todos, filter }) {
  const [newTodo, setNewTodo] = useState('');
  // ✅ Does not re-run getFilteredTodos() unless todos or filter change
  // ✅ todos나 filter가 변하지 않는 한 getFilteredTodos()가 재실행되지 않음
  const visibleTodos = useMemo(() => getFilteredTodos(todos, filter), [todos, filter]);
  // ...
}

 

prop이 변경되면 모든 state 재설정하기

- prop이 변경되었을 때, state를 변경하고 싶다면 key 속성을 이용하여 state를 재설정할 수 있습니다.

- 서로 다른 key를 받게 되면 state를 공유하지않고, 별개의 컴포넌들로 취급한다고 생각하시면 됩니다.

- 렌더링 과정: key가 변경 -> DOM 다시 생성 -> state 재설정 -> 하위 컴포넌트 모든 자식들의 state 재설정

 

이벤트 핸들러 간 로직 공유

- 이벤트를 발생해야하는 경우에는 직접 이벤트 핸드러를 제작해서 해당 버튼을 클릭했을 때 실행되게 onClick을 이용하는게 좋습니다.(예:post, 연쇄계산)

- 이렇게 사용하게되면, 해당 함수가 어떤 이벤트를 발생하는지 한눈에 확인이 쉬워지며 버그 발생 확률이 낮아집니다.

 

부모에게 데이터 전달하기

- React에서 데이터는 부모 컴포넌트에서 자식 컴포넌트로 흐른다.

- 어떤 컴포넌트가 잘못된 prop을 전달하거나 잘못된 state를 가지고 있는지 찾아냄으로써 정보의 출처 추적이 쉽다(컴포너트 체인)

- 데이터는 부모컴포넌트에서 데이터를 페치하고, 자식에게 전달하는 게 좋습니다.

 

function Comment() {
  const data = {//데이터를 받아오는 로직}  
  return <CommentList data={data} />;
}

function CommentList({ data }) {
  // ...
}

 

 

참고

https://react-ko.dev/learn/you-might-not-need-an-effect