I T H

[React_Basic 6] TODO 리스트 만들기 5 - React.memo(렌더링최적화) 본문

React Basic

[React_Basic 6] TODO 리스트 만들기 5 - React.memo(렌더링최적화)

thdev 2024. 1. 25. 10:32
React.memo를 사용해서 불필요한 렌더링을 최소화 할수있다.
아래 화면은 글씨를 쓸때마다 List,Lists 컴포넌트가 랜더링 된다.
불필요한 렌더링을 최소화시키려면 해당 컴포넌트를 React.memo로 감싸주면 됨.

 

[Lists.js]

-  rafce를 눌러서 함수 형식을 바꿔준후(function -> const)

-  React.memo로 감싸준다.

import React from "react";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import List from "./List";

const Lists = React.memo(({ todoData, setTodoData }) => {
  console.log("Lists component");
  const handleEnd = (result) => {
    console.log("result", result);

    if (!result.destination) return;
    const newTodoData = todoData;

    //1. 변경시키는 아이템을 배열에서 지워줌.
    //2. return 값으로 지워진 아이템을 잡아줌.
    const [reorderedItem] = newTodoData.splice(result.source.index, 1);

    //원하는 자리에 reorderedItem을 insert 해줍니다.
    newTodoData.splice(result.destination.index, 0, reorderedItem);
    setTodoData(newTodoData);
  };
  return (
    <div>
      <DragDropContext onDragEnd={handleEnd}>
        <Droppable droppableId="todo">
          {(provided) => (
            <div {...provided.droppableProps} ref={provided.innerRef}>
              {todoData.map((data, index) => (
                <Draggable
                  key={data.id}
                  draggableId={data.id.toString()}
                  index={index}
                >
                  {(provided, snapshot) => (
                    <List
                      key={data.id}
                      id={data.id}
                      title={data.title}
                      completeted={data.completeted}
                      todoData={todoData}
                      setTodoData={setTodoData}
                      provided={provided}
                      snapshot={snapshot}
                    />
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    </div>
  );
});

export default Lists;

[List.js]

import React from "react";

const List = React.memo(
  ({ id, title, completed, todoData, setTodoData, provided, snapshot }) => {
    console.log("List component");

    const handleClick = (id) => {
      let newTodoData = todoData.filter((data) => data.id !== id); //클릭하지 않은 key값 데이터만 뜨게 됨.
      console.log("newTodoData", newTodoData);
      setTodoData(newTodoData);
    };

    const handleCompleteChange = (id) => {
      let newTodoData = todoData.map((data) => {
        if (data.id === id) {
          data.completed = !data.completed;
        }
        return data;
      });
      setTodoData(newTodoData);
    };

    return (
      <div
        key={id}
        {...provided.draggableProps}
        ref={provided.innerRef}
        {...provided.dragHandleProps}
        className={`${
          snapshot.isDragging ? "bg-gray-400" : "bg-gray-100"
        } flex items-center justify-between w-full px-4 py-1 my-2 text-gray-600 bg-gray-100 border rounded`}
      >
        <div className="items-center">
          <input
            type="checkbox"
            defaultChecked={false}
            onChange={() => handleCompleteChange(id)}
          />
          <span className={completed ? "line-through" : undefined}>
            {title}
          </span>
        </div>
        <div className="items-center">
          <button
            className="px-4 py-2 float-right"
            onClick={() => handleClick(id)}
          >
            X
          </button>
        </div>
      </div>
    );
  }
);

export default List;

[결과화면]

- 글씨쓸때 List와 Lists컴포넌트가 랜더링 되지 않고, App,Form컴포넌트만 랜더링 됨.