1편 props drilling (context, redux)

렐루·2024년 5월 24일
0

리액트

목록 보기
16/20

가계부를 props drilling으로!

위의 그림은 월별 가게부 프로그램을 props drilling, context, redux 중에 첫번째 props drilling 을 이용하여 만든 코드의 관계를 설명한 그림이다.

원래는 데이터 전체는 백앤드에서 관리하지만 모의 프로젝트인 관계로 데이터를 프론트 영역에서 관리하게 되었다.
배열이 아니라 Map 객체를 사용하여 관리함으로 데이터를 id로 쉽게 접근할 수 있도록 만들었다.

랜더링이 최대한 적게 되게 하기 위해서는 state가 어디서 변하고 있는지, 어디까지 영향을 미치고 있는지 파악해야할 것 같아서 먼저 관계도를 그림으로 그리고 작업을 시작했다.


불필요한 state를 적게 사용하기 위해서 App에서 데이터를 관리하고 home에서 최대한 값을 계산해서 내려줬다.

2. 랜더링을 한번 더 줄여보자!

코드를 다 작성하고 나니 월을 바꿀때마다 서브밋폼이 계속 불필요하게 업데이트 되고 있음을 깨달았다.

그래서 관계도에서 홈이 세개 컴포넌트를 모두 자식으로 품지 않고 서브밋폼 하나, 그래프와 리스트를 품는 컴포넌트 하나 이렇게 관리하고 달력선택하는 useState를 홈이 아닌 두개를 품은 컴포넌트에서 관리하게 함으로써 달을 바꾸더라도 위의 서브밋 폼이 변하지 못하게 만들었다!!

3. 깊어진 props 전달

이렇게 하면 위의 문제는 해결할 수 있지만 props의 깊이가 계속 깊어짐을 알 수 있다.
지금이야 너무 간단한 기능을 구현하는 중이기에 몇단계 거치지 않지만 나중에 복잡한 기능이 모인 실사이트를 유지보수하게되는 경우에는 이 관계가 매우 중첩되어 관리가 매우 어려울 확률이 높다.

따라서 다음 블로그에서는 같은 기능을 context, redux로도 구현하여 글을 작성해보겠다!

Home 코드

// 이전 홈
import AccountLogMonthlyStatus from "../components/AccountLogMonthlyStatus";
import SumbmitForm from "../components/SumbmitForm";
import { useEffect, useState } from "react";
import AccountLogGraph from "./AccountLogGraph";
import AccountLogList from "./AccountLogList";
import MonthSelect from "./MonthSelect";

function Home({ logMap, submitLogForm }) {
  const [selectedMonth, setSelectedMonth] = useState("");

  // 배열로 추출
  const selectedMonthGraphObj = {};
  let totalAmout = 0;
  const logValues = Array.from(logMap.values());
  const seletedMonthLogList = logValues.filter((logObj) => {
    if (new Date(logObj.date).getMonth() === parseInt(selectedMonth)) {
      if (selectedMonthGraphObj[logObj.title]) {
        selectedMonthGraphObj[logObj.title] =
          parseInt(selectedMonthGraphObj[logObj.title]) +
          parseInt(logObj.amount);
      } else {
        selectedMonthGraphObj[logObj.title] = logObj.amount;
      }
      totalAmout += parseInt(logObj.amount);
      return true;
    }
    return false;
  });
  useEffect(() => {
    const prevSelectedMonth = window.localStorage.getItem("selectedMonth");
    console.log(prevSelectedMonth);
    if (prevSelectedMonth) {
      setSelectedMonth(prevSelectedMonth);
    } else {
      const newDate = new Date().getMonth();
      window.localStorage.setItem("selectedMonth", newDate);
      setSelectedMonth(newDate);
    }
  }, []);
  return (
    <>
      <SumbmitForm submitLogForm={submitLogForm} />
      <AccountLogMonthlyStatus logMap={logMap} />
    </>
  );
}

// 이후 홈
import AccountLogMonthlyStatus from "../components/AccountLogMonthlyStatus";
import SumbmitForm from "../components/SumbmitForm";

function Home({ logMap, submitLogForm }) {
  return (
    <>
      <MonthSelect
        selectedMonth={selectedMonth}
        setSelectedMonth={setSelectedMonth}
      />
      <AccountLogGraph
        selectedMonthGraphObj={selectedMonthGraphObj}
        selectedMonth={selectedMonth}
        totalAmout={totalAmout}
      />
      <AccountLogList seletedMonthLogList={seletedMonthLogList} />
      <AccountLogMonthlyStatus logMap={logMap} />
    </>
  );
}

export default Home;

컴포넌트를 분리함으로써 위의 코드와 아래의 코드가 확실하게 깔끔해짐을 알 수 있다.

input 부분 랜더링도 안되고 있음!! 해결완료!!

감사합니다!!!

profile
프론트 공부중입니다!

0개의 댓글