코테이토 동아리/[코테이토]React 스터디 5기

11장. 컴포넌트 성능 최적화

Xerath(제라스) 2023. 2. 3. 12:39
728x90
반응형

- useState 사용 시

useState(func()) //이러면 리렌더링될 때마다 func함수가 호출됨.
useState(func) //이런 식으로 파라미터를 함수 형태로 넣어주면 컴포넌트가 처음 렌더링딜 때만 func 함수 실행함.

- 느려지는 원인 분석

1. 자신이 전달받은 props가 변경될 때

2. 자신의 state가 바뀔 때

3. 부모 컴포넌트가 리렌더링될 때

4. forceUpdate 함수가 실행될 때

 

컴포넌트의 개수가 많은데 모두 리렌더링을 하게 되면 느려지는 이슈 발생

-> 컴포넌트 리렌더링 성능을 최적화해줘야 함.

 

1. React.memo를 활용

import React from 'react';
import {
  MdCheckBoxOutlineBlank,
  MdCheckBox,
  MdRemoveCircleOutline,
} from 'react-icons/md';
import './TodoListItem.scss';
import cn from 'classnames';

const TodoListItem = ({ todo, onRemove, onToggle, style }) => {
  const { id, text, checked } = todo;
  return (
    <div className="TodoListItem-virtualized" style={style}>
      <div className="TodoListItem">
        <div
          className={cn('checkbox', { checked })}
          onClick={() => onToggle(id)}
        >
          {checked ? <MdCheckBox /> : <MdCheckBoxOutlineBlank />}
          <div className="text">{text}</div>
        </div>
        <div className="remove" onClick={() => onRemove(id)}>
          <MdRemoveCircleOutline />
        </div>
      </div>
    </div>
  );
};

export default React.memo(TodoListItem); //이 부분처럼 처리해주면 됨.

-> 이런 식으로 React.memo를 써주면 컴포넌트의 props(todo, onRemove, onToggle, style)가 변경되지 않을 시 리렌더링하지 않음.

2. 함수가 바뀌지 않게 하기

1) useState의 함수형 업데이트

//이런 식으로 이전의 state(nowTodos)를 가지고 다음 state(nowTodos.concat(todo))를 선언해주면 됨.
setTodo(nowTodos => nowTodos.concat(todo));

2) useReducer 사용하기

useReducer를 사용하면 상태를 업데이트하는 로직을 모아서 컴포넌트 바깥에 둘 수 있음.

...
function createBulkTodos() {
  const array = [];
  for (let i = 1; i <= 2500; i++) {
    array.push({
      id: i,
      text: `Todo ${i}`,
      checked: false,
    });
  }
  return array;
}

function todoReducer(todos, action) {
  switch (action.type) {
    case 'INSERT':
      return action.tempTodos;
    case 'REMOVE':
      return todos.filter((todo) => todo.id !== action.id);
    case 'TOGGLE':
      return todos.map((todo) =>
        todo.id === action.id ? { ...todo, checked: !todo.checked } : todo,
      );
    default:
      return todos;
  }
}
const App = () => {
  const [todos, dispatch] = useReducer(todoReducer, undefined, createBulkTodos); //이때 두번째 파라미터는 initialState값임.

  const nextId = useRef(2501);
  const onInsert = useCallback(
    (text) => {
      const tempTodos = [...todos, { id: nextId, text, checked: false }];
      dispatch({ type: 'INSERT', tempTodos });
      nextId.current += 1;
    },
    [todos],
  );
  ...

3. 불변성 유지하는 방법

- 불변성을 지킨다: 기존의 값을 직접 수정하지 않으면서 새로운 값을 만들어 내는 것.

 

//이런 방식으로 하면 얕은 복사만...!!
const nextTodos = [...todos];


//이렇게 하면 새로운 객체를 할당하게 됨.
nextTodos[0] = {
	...nextTodos[0],
    checked: false,
};

4. react-virtualized를 활용

이게 뭔데?? 스크롤하기 전에 보이지 않는 컴포넌트들은 렌더링하지 않고 크기만 차지하게끔 하는 라이브러리.

 

 

 

모든 작업에 최적화를 할 필요는 없음!

하지만 보여줄 항목이 많아져서 업데이트가 종종 발생한다면 최적화 필요!

728x90
반응형