리액트를 다루는 기술 - 11장

velbie·2020년 10월 23일
0
post-thumbnail

11장까지 오기위해 1 ~ 10장 을 두번 읽었습니다.

많은 데이터 렌더링하기

많은 데이터를 리턴하는 함수를 만들어서 2,500 개를 자동으로 생성했습니다.

const [todos.setTodos] = useState(createBulkTodos);

주의할 점은 useState의 기본값에 함수를 넣어 주었다는 것 입니다.(배열이 리턴됩니다.) 여기서 useState(createBulkTodos()) 라고 작성하면 리렌더링될 때마다 createBulkTodos 함수가 호출되지만, useState(createBulkTodos) 처럼 파라미터를 함수 형태로 넣어주면 컴포넌트가 처음 렌더링 될때만 createBulkTodo 함수가 실행됩니다!

느려지는 원인 분석

컴포넌트는 다음과 같은 상황에서 리렌더링이 발생합니다.

  • 자신이 전달받은 props가 변경될 때
  • 자신의 state가 바뀔 때
  • 부모 컴포넌트가 리렌더링 될 때 -> 함수 최적화!!!. React.memo 최적화!!
  • fourceUpdate 함수가 실행 될 때
    '할 일 1' 항목을 체크할 경우 App 컴포넌트의 state가 변경되면서 App 컴포넌트가 리렌더링 됩니다. 부모 컴포넌트가 리렌더링되었으니 TodoList 컴포넌트가 리렌더링 되고 그안의 무수한 컴포넌트들이 리렌더링 됩니다. 할일 1 항목을 리렌더링 되어야 하는것이 맞지만, '할 일 2' 부터 '할일 2500' 까지는 리렌더링을 안 해도 되는 상황인데 모두 리렌더링 되고 있습니다.
    리렌더링이 불 필요할 때는 리렌더링을 방지해 주어야합니다.

React.memo (컴포넌트)

컴포넌트의 props가 바뀌지 않았다면 리렌더링 하지 않도록 설정하여 함수형 컴포넌트의 리렌더링 성능을 최적화해 줄수 있습니다.

TodoListItem.js

const TodoListItem = ({ todo, onRemove, onToggle} => {
	  (...)
});

export default React.memo(TodoListItem);

이제 TodoListItem 컴포넌트는 todo, onRemove, onToggle 이 바뀌지 않으면 리렌더링을 하지 않습니다.

또 다른 최적화 (함수)

  1. 아무때나 리렌더링 됨 -> 그럴때마다 함수가 생성되고 실행됩니다.
  2. useCallback(,[]) 이용해서 처음에만 함수생성하게 함 -> 그래도 리렌더링할때마다 실행됨
  3. 특정 상태 업데이트 할때만 useCallback(,[state])함수 생성하고 실행하게 함
  4. 처음에만 함수생성 후 특정 상태 업데이트만 작동하도록 함

아래 처럼 바꿈, [] 이부분 주의

const onRemove = useCallback(id => {
	setTodos(todo => todos.filter(todo => todo.id !== id));
}, [])

원래는 아래와 같았음 차이점 확실히 알고가면 좋을것 같습니다.

const onRemove = useCallback(
    (id) => {
      setTodos(todos.filter((todo) => todo.id !== id));
    },
    [todos],
  );

불변성의 중요성

어떤 객체A에서 참조로 복사한경우, 복사한 객체B를 수정했을 때,
B를 수정한경우 A도 수정되니깐 (같은거니깐)
A에서 B로 어떻게 수정됐는지 알수가 없어 비교가 안되니깐 그럼 최적화도 불가능해집니다.

그렇기 때문에 얕은복사를 해서 불변성을 유지해야하는데, 얕은복사도 그 안에 요소를 비교하면 사실 같은요소로 판단하니깐 깊은복사를 해줘서 불변성을 유지해야하는데.. 그럼 복잡해지니깐 immer 라는 라이브러리의 도움을 받으면 편하게 작업할수 있습니다.

react-virtualized

리스트를 렌더링 할때 스크롤 아래에 있는 부분도 렌더링해서 비효율적입니다.
react-vitualized 를 사용하면 리스트 컴포넌트에서 스크롤되기 전에 보이지 않는 컴포넌트는 렌더링하지 않고 크기만 차지하게끔 할 수 있습니다. 그리고 만약 스크롤되면 해당 스크롤 위치에서 보여 주어야 할 컴포넌트를 자연스럽게 렌더링시키죠.

profile
안녕하세요

0개의 댓글