[TIL] 05.29 :: 개인과제 제출

yeseul·2024년 5월 29일

<TIL>

목록 보기
19/43

- 지출내용 수정 및 삭제 / pie chart



- 유효성검사 / 지출내용 생성

지난번 기능구현 이후로 스탠다드반 수업을 통해 context api, redux 를 이용해서 전역관리 하는 법에 대해 복습을 했다. 개인과제할때 도움이 되는 스탠다드 과제도 내주셔서 그거 먼저 풀면서 연습을 하고 개인과제에 비슷하게 활용했다.
확실히 실시간 수업을 통해 지난번 개념 복습 + 과제로 한번 더 복습하니 훨-씬 도움이 많이 된다. 특히 개인과제에 접목시킬때 예전엔 어떻게할지 감도 안잡혔었는데 todolist 과제때부터 가계부 과제까지 리액트 훅에대해 전체적인 개념이 잡힌 느낌이다.

✅ react-router-dom 을 활용한 페이지 이동처리
✅ styled-component 를 이용한 스타일링 적용
✅ context api 를 이용한 전역 상태 관리
✅ redux 를 이용한 전역 상태 관리

props-drilling 으로 기능구현하는 부분이 생각보다 오래걸렸고, 오히려 전역상태 관리하는 브랜치로 리팩토링을 생각보다 빠르게했다.
Detail 페이지에서 로컬스토리지에 접근하여 데이터를 수정하는 부분을 useRef 로 사용해보느라 개념이 생소했지만, state 보다 current 로 참조해서 접근하는부분이 훨씬 단순하다고 느꼈다.
과제를 하면서 리렌더링을 최대한 적게하는 법이 뭘까, 어떤데이터를 보관?유지?? 시켜놔야 효율적일까를 항상 고민하고 있다.-> 이 부분이 해결되면 코드도 훨!씬! 간결해진다는걸 배웠다..!!

다만.. 마지막에 Redux 브랜치까지 마무리한 후, Nivo - pie chart 로 지출 요약 그래프를 첨부하려고 했는데 스타일링에 막히는 부분이 있어서 마지막 시간까지 탈탈 털어서 해결했다.....
그래도 .. 마지막에 스타일링 하기위해 기능구현 하는것도 있으니까... 애써 멘탈 잡고 ㅎ 라이브러리 설치가 안되는거때문에 못하는건 너무 억울해서 될때까지 했다.
차트 정보는 왤케 없는지!! (*노트북 재부팅후 좀 냅두다가 다시 vscode 관리자모드로 실행하고 라이브러리 설치하니까 잘되더라...)

Nivo는 자주 쓸거 같으니 따로 포스팅을 해야겠다. 결과물을 보니 너무 만족스러운 그래프라 오류 해결하고나니까 너~무 행복하다.

아직은 useContext 와 Redux 를 언제 어떤 데이터를 분리해서 사용해야되는지 감이 잘 안온다ㅜㅠ 다음 팀플때는 일부러 기능을 나눠서 적용시켜보고싶다. 예를들어 다크모드/라이트모드엔 context 를 사용한다던지..!!


* 폴더구조


✔️ props-drilling -> Context

  • Router -> Home -> InputForm 까지 props 가 깊어진다면.. 하고 테스트해본 코드.
    직접 작성하면서도 이건아니다 x50번 반복했다.🥲
// DataContext.jsx
import React, { createContext } from "react";
import { useState } from "react";

export const DataContext = createContext();
export const DataProvider = ({ children }) => {
  const [activeIndex, setActiveIndex] = useState("");
  const [data, setData] = useState([]);

  return (
    <DataContext.Provider
      value={{ activeIndex, setActiveIndex, data, setData }}
    >
      {children}
    </DataContext.Provider>
  );
};
  • 지출내역이 담긴 data 와 setData, 버튼을 클릭할때 활성화되는 activeIndex, setActiveIndex 를 전역상태로 변경했다.
  • import 를 꼭!! 신경써서 작성하자.

💭 클릭됐을때의 조건부 렌더링을 위한 변수도 전역상태로 관리하는게 맞는지 애매하다..

  • context 브랜치로 리팩토링할때 Home 에서 List 로 props 내려줬던 activeIndex는 월 버튼 클릭할때와 차트가 보일때 사용되는데, 나름 '월' 을 기준으로 데이터를 필터링 하는 경우가 많다고 생각되어 전역상태로 관리하는게 맞는거 같단 생각이 들었다.
    다만 전체 데이터를 아우르는 변수는 아니다보니.. 헷갈려서 질문을 남겼다.

[Question] 🤔 몇번 안쓰이는 (activeIndex : 클릭된 버튼)도 전역상태에서 관리하는게 맞나요??


✔️ Context -> Redux (RTK)

  • dummyData 도 따로 json 파일로 분리.
  • Header 컴포넌트 생성.
    • 페이지마다 h1 타이틀의 이름은 props 로 받았다. 굳이 전역상태로 관리할 필요가 없는 경우는 props 로 내려주는게 더 간단하다!
// Header.jsx
const Header = ({ title }) => {
  return (
    <StHeader>
      <StTitle>{title}</StTitle>
      <StIcon src={Icon} alt="Icon" />
    </StHeader>
  );
};

// Detail.jsx
return(<Header title="Modify expenditure" />)
// Home.jsx
return(<Header title="MONEY RECORD" />)
  • 과제 해설 영상을 보니, 제출 전, 리팩토링할때 빨리 끝난 이유가 있었다. 함수도 리듀서로 관리할 수 있는데, 상태관리함수만 추가해놓고 다른 컴포넌트에 있는 수정,삭제함수는 그냥 냅뒀었다.
    -> 로컬스토리지에서 가져오는 초기데이터 설정이나, 변경된 데이터의 경우 전역상태로 관리하는게 좋다는 생각이 든다. 어차피 수정/삭제를 할 경우 매번 로컬스토리지에 접근하게되므로..
// 수정한 코드
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  activeIndex: "",
  data: JSON.parse(localStorage.getItem("localData")) || [],
};

const dataSlice = createSlice({
  name: "data",
  initialState,
  reducers: {
    setActiveIndex: (state, action) => {
      state.activeIndex = action.payload;
    },
    setData: (state, action) => {
      state.data = action.payload;
      localStorage.setItem("localData", JSON.stringify(action.payload));
    },
    modifyData: (state, action) => {
      const { id, date, category, price, description } = action.payload;
      const updatedData = state.data.map((item) =>
        item.id === id ? { id, date, category, price, description } : item
      );
      state.data = updatedData;
      localStorage.setItem("localData", JSON.stringify(updatedData));
    },
    deleteData: (state, action) => {
      const id = action.payload;
      const deletedData = state.data.filter((item) => item.id !== id);
      state.data = deletedData;
      localStorage.setItem("localData", JSON.stringify(deletedData));
    },
  },
});

export const { setActiveIndex, setData, modifyData, deleteData } = dataSlice.actions;
export default dataSlice.reducer;

💭 Redux 브랜치에서 최종 스타일링까지 마무리했는데, merge 할 엄두가 안나네!

기능구현을 우선으로 하고 스타일링을 할 생각이었어서 차트삽입이나 헤더부분을 나중에 구현했다.
Redux 가 최종 브랜치가 되었는데, context 랑 props-drilling 브랜치에는 스타일링 적용이 하나도 안된게 너무 아쉬웠다. merge를 하기엔 기능 부분을 구현한 코드도 함께 있어서 뭔가 충돌이 많이 발생할듯해서 그대로 제출했고, 튜터님께 아래와 같은 질문을 남겼다!

[Question] 🤔 스타일드 컴포넌트를 사용해서 CSS 부분을 jsx 하나의 파일에서 관리하면, 스타일링만 변화시켰는데도 merge 할때 충돌나는 경우가 많나요?! 스타일 변경만 하는 브랜치를 따로 처음에 만들었어야되는건가 하는 생각이 듭니다..!


* 회고

지난번 과제때 튜터님께 css 파일 분리에 대해 여쭤보았을때 styled-components 를 추천해주신게 이해가 됐다. 하나의 파일 안에서 관리할 수 있어서 폴더구조도 훨씬 깔끔했고, 직관적이라 해당 부분의 스타일을 쉽게 수정할 수 있었다. 또한 헤더의 경우 컴포넌트화를 통해 detail 컴포넌트에서도 똑같이 사용할 수 있어서 정말 편했다! 스타일드 컴포넌트를 통해 동적으로 스타일을 다르게 적용하는 부분도 코드가 한결 짧아져서 좋았다.
다만, 아직은 일반 컴포넌트인지 스타일드 컴포넌트인지 헷갈리므로 컴포넌트 이름 앞에 St 를 붙이는게 훨씬 편하다.

useState 는 input 같이 제어 컴포넌트로 바로 상태를 관리할 때 쓰면 좋은거 같고, useRef 는 current 로 값을 보관할 수 있으니까 데이터를 모아서 한번에 업데이트(리렌더링) 시킬 때 사용하기 좋은 것 같다. 훅 사용시 import 가 자동으로 안되는 경우가 많으니 꼭꼭 신경써야겠다고 느꼈다.
5번 이상은 까먹고 콘솔에 찍힌 에러 보고 알았다ㅜㅜ

상황에 맞게 훅과 리덕스를 적용하기가 아직은 익숙하지 않지만, 하다보면 익숙해지겠지 ㅎㅎ
팀프로젝트에서 다양하게 연습해보자!🤠

0개의 댓글