React/일정관리 프로젝트

[React TodoList] 불변성, 최적화, 렌더링 최적화

Judith Hopps 2023. 3. 15. 09:44
반응형

리액트 투두리스트 보완

 

 

불변성의 중요성

불변성이란?
기존의 값을 수정하지 않으면서 새로운 값을 만들어 내는 것

 

 

TodoList 컴포넌트 최적화 하기

리스트 내부에서 사용하는 컴포넌트도 최적화 해야 하고, 

리스트로 사용되는 컴포넌트 자체도 최적화해 주는 것이 좋다.

 

 

 

react-virtualized를 사용한 렌더링 최적화 하기

리스트 컴포넌트에서 스크롤 되기 전에 보이지 않는 컴포넌트는 렌더링 하지 않고 크기만 차지하게 끔 할 수 있다.

스크롤 이벤트 발생 시, 스크롤 위치에서 보여 주어야 할 컴포넌트를 자연스럽게 렌더링 시킨다.

이 라이브러리를 사용하면 낭비되는 자원을 아주 쉽게 아낄 수 있다. 

 

사용방법

 

1. 패키지 설치 

npm install react-virtualized

 

2. UI 컴포넌트 px 알아보기

 

 

 

3. TodoList.js 수정

 

import React, { useCallback } from 'react';
import { List } from 'react-virtualized';
import TodoListItem from './TodoListItem';
import './TodoList.scss';

const TodoList = ({ todos, onRemove, onToggle }) => {
  const rowRenderer = useCallback(
    ({ index, key, style }) => {
      const todo = todos[index];
      return (
        <TodoListItem
          todo={todo}
          key={key}
          onRemove={onRemove}
          onToggle={onToggle}
          style={style}
        />
      );
    },
    [onRemove, onToggle, todos],
  );
  return (
    // 각 항목의 길이는 가로 512, 세로 56.67(첫번째 칸은 테두리가 없어 세로 56) 이다.
    <List
      className="TodoList"
      width={512} // 전체 크기
      height={453.44} // 전체 높이
      rowCount={todos.length} // 항목 개수
      rowHeight={56.67} // 항목 높이
      rowRenderer={rowRenderer} // 항목을 렌더링할 때 쓰는 함수
      list={todos} // 배열
      style={{ outline: 'none' }} // List에 기본 적용되는 outline 스타일 제거
    />
  );
};

export default React.memo(TodoList);

 

 

4. TodoListItem 

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

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);

 

 

5. TodoListItem.scss

.TodoListItem-virtualized {
  &:nth-child(even) {
    background-color: #f8f9fa;
  }
  & + & {
    border-top: 1px solid #dee2e6;
  }

}
.TodoListItem{
  padding: 1rem;
  display: flex;
  align-items: center;
  
  .checkbox{
    cursor: pointer;
    flex : 1;
    display: flex;
    align-items: center;
    svg {
      font-size:  1.5rem;
    }
    .text {
      margin-left: 0.5rem;
      flex : 1
    }
    &.checked {
      svg{
        color : #22b8cf;
      }
      .text{
        color :#adb5bd;
        text-decoration: line-through;
      }
    }
  }
  .remove {
    display: flex;
    align-items: center;
    font-size: 1.5rem;
    color:#ff6b6b;
    cursor: pointer;
    &.hover {
      color :#ff8787;
    }
  }

  
}

 

 

Final , 성능 측정

반응형