React당

React - 스파게티코드 지양을 위한 Component 구성 방법

이히당 2024. 2. 17. 14:12

목표 : 반복되는 코드는 컴포넌트로 따로빼는것이 다방면으로 효율적이다.

하나의 예시로 테이블안에 들어갈 아이템들은 반복되는 것이기에 하나씩 다 구현하는 것은 정말 말도안된다.

보통 이런 경우에는 map함수를 사용해 테이블 안에 들어갈 데이터를 적절하게 조작하여 보여준다.

예시코드를 보자

 <tbody>  
    {isLoading ? (  
      <tr>  
        <td colSpan="3">Is Loading</td>  
      </tr>    ) : !study || study.length === 0 ? (  
      <tr>  
        <td colSpan="5"></td>  
      </tr>    ) : (  
      <>  
        {study.map((todoItem, index) => (  
          <tr key={todoItem.id} className="border-b border-black">  
            {/*투두 완료 유무 + 완료 체크 기능*/}  
            <td className="p-3 text-sm text-center">  
              <span                onClick={() =>  
                  handleCheckbox(todoItem.id, todoItem.study_completed)  
                }  
                className={`p-1.5 text-xs font-medium tracking-wider rounded-md ${  
                  todoItem.study_completed ? "bg-green-300" : "bg-red-300"  
                }`}  
              >  
                {todoItem.study_completed ? "Done" : "Incomplete"}  
              </span>  
            </td>            {/*투두 내용*/}  
            <td className="p-3 text-sm" title={todoItem.id}>  
              {todoItem.study_todo}  
            </td>  
            {/*공부한 시간*/}  
            <td className="p-3 text-sm font-medium">  
              {todoItem.study_time}  
            </td>  
            {/*수정 및 삭제*/}  
            <td className="p-3 text-sm font-medium grid grid-flow-col items-center mt-5">  
              <span>                <label htmlFor="my-modal">  
                  <MdEditNote                    onClick={() => setEditText(todoItem)}  
                    className="text-xl cursor-pointer"  
                  />  
                </label>              </span>              <span className="text-xl cursor-pointer">  
                <MdOutlineDeleteOutline                  onClick={() => handleDelete(todoItem.id)}  
                />  
              </span>            </td>            <td className="p-3 text-sm" title={todoItem.id}>  
              <FaRegCheckCircle />            </td>          </tr>        ))}  
      </>  
    )}  
  </tbody> 

isLoading변수는 데이터가 제대로 넘어오기 전까지의 처리를 도와준다.
데이터가 넘어오는 동안에도 사용자에게 화면을 보여주어야하기 때문에 추가했다.

데이터가 잘 넘어오면 map함수가 실행된다.
물론 이 코드도 모든 테이블 아이템을 일일이 하드코딩하지 않았기에 괜찮다고 볼 수 있으나, 컴포넌트화를 하면 더욱 간결하고 직관적으로 구성할 수 있다.

이제 컴포넌트로 빼보자.

import React from "react";  
import {  
  MdOutlineDeleteOutline,  
  MdEditNote,  
  MdOutlineCheckBox,  
  MdOutlineCheckBoxOutlineBlank,  
} from "react-icons/md";  
import { FaRegCheckCircle, FaCheck } from "react-icons/fa";  
import { RiCalendarTodoFill } from "react-icons/ri";  
import { RxLapTimer } from "react-icons/rx";  

const TodoItem = ({ todoItem, handleCheckbox, handleDelete, setEditText }) => {  
  return (  
    <tr key={todoItem.id} className="border-b border-black">  
      {/*투두 완료 유무 + 완료 체크 기능*/}  
      <td className="p-3 text-sm text-center">  
        <span          onClick={() => handleCheckbox(todoItem.id, todoItem.study_completed)}  
          className={`p-1.5 text-xs font-medium tracking-wider rounded-md ${  
            todoItem.study_completed ? "bg-green-300" : "bg-red-300"  
          }`}  
        >  
          {todoItem.study_completed ? "Done" : "Incomplete"}  
        </span>  
      </td>      {/*투두 내용*/}  
      <td className="p-3 text-sm" title={todoItem.id}>  
        {todoItem.study_todo}  
      </td>  
      {/*공부한 시간*/}  
      <td className="p-3 text-sm font-medium">{todoItem.study_time}</td>  
      {/*수정 및 삭제*/}  
      <td className="p-3 text-sm font-medium grid grid-flow-col items-center mt-5">  
        <span>          <label htmlFor="my-modal">  
            <MdEditNote              onClick={() => setEditText(todoItem)}  
              className="text-xl cursor-pointer"  
            />  
          </label>        </span>        <span className="text-xl cursor-pointer">  
          <MdOutlineDeleteOutline onClick={() => handleDelete(todoItem.id)} />  
        </span>      </td>      <td className="p-3 text-sm" title={todoItem.id}>  
        <FaRegCheckCircle />      </td>    </tr>  );  
};  

export default TodoItem;

일단 이렇게 TodoItem이라는 컴포넌트를 새로이 만들었다.

이제 이 컴포넌트를 테이블에 적용하면 된다.

import TodoItem from './TodoItem';

// Table 컴포넌트 내부에서 TodoItem 컴포넌트 사용
{study.map((todoItem, index) => (
  <TodoItem
    key={index}
    todoItem={todoItem}
    handleCheckbox={handleCheckbox}
    handleDelete={handleDelete}
    setEditText={setEditText}
  />
))}

코드가 훨씬 간결해졌다.

여기서 이제 item에 들어갈 내용을 수정하고 싶으면 해당 컴포넌트 파일안에서 수정해주면 되기 때문에 상당히 직관적이다!

앞으로도 깔끔하고 이해하기 쉬운 코드를 짜기위해 노력해보자><
끗!

728x90