리액트 숙련 - [과제] 아티스트 컬렉션 만들기 (7) - 리덕스와 완료..

새벽로즈·2023년 11월 20일
1

TIL

목록 보기
49/72
post-thumbnail

과제의 마지막 단계 리덕스..

context 했던 2가지, 모든 레터를 관리하는 letters와 선택한 멤버를 관리하는 selectMember를 리덕스로 하기로 했다.

금요일 밤, 진영튜터님께 질문하러 갔었다.
뭔지 대충 알거같기는 한데.. 어려워서 도움을 요청했었는데,
같이 진행하다가, 과제와 다르게 리덕스 개념을 아는게 중요하다고 하셨다. 일과시간 21시가 끝난뒤 21시 45분에 나 때문에 특강이 열렸다.

1시간을 개념, 1시간조금넘어서 어떤식으로 활용하는지 알려주셨고
개념은 확실히 알게 되었다.

리덕스 개념

Store : Store가 들어가 있는 컴포넌트들에게서 접근 가능한 상태 저장소 (보통 전역에서 접근함)

State : 저장하고 변경하고 관리하는 등의 일종의 데이터 , 즉 상태

Ruducer : State를 Action에 따라 변경해주는 함수

☞ Ruducer의 쉬운 예시 : State를 작업지시서의 내용에 따라 변경하는 공장)

Action

  • 보통 객체
  • 필수로 들어가야하는 것은 액션의 Type
  • 선택으로 들어 갈수 있는 것은 Payload ☞ 액션과 함께 보내는 값

☞ Action의 쉬운 예시 : 리듀서 공장에 보내는 작업지시서

Action Creator

  • 액션을 만들어 주는 함수
  • 일반적으로 하나의 액션은 하나의 액션 크리에이터를 대응해서 만듬

☞ Action Creator의 쉬운 예시 : 공장에 보낼 작업지시서를 만드는 사람

Dispatch

  • Action을 Reducer로 보내는 행위 또는 함수

☞ Dispatch의 쉬운 예시 : 작업지시서를 공장에 보내는 행위

리덕스 써보기

  • Context API를 사용하여 전역 상태를 관리하던 코드를 Redux로 변경해야했다.

1. Redux 스토어 생성

// configStore.js
import { combineReducers, createStore } from "redux";
import letterReducer from "redux/reducers/letterReducer";
import selectMemberReducer from "redux/reducers/selectMemberReducer";

const rootReducer = combineReducers({
  letter: letterReducer,
  selectMember: selectMemberReducer,
});

const store = createStore(rootReducer);
export default store;

☞ 위에처럼 설정하기

2. Provider 설정

//Router.js
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Home from "pages/Home";
import Detail from "pages/Detail";
import { Provider } from "react-redux"; // 추가된 부분
import store from "redux/config/configStore";

const Router = () => {
  return (
    <BrowserRouter>
      <Provider store={store}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/detail/:id" element={<Detail />} />
        </Routes>
      </Provider>
    </BrowserRouter>
  );
};

export default Router;

☞ 로 감싸주기

3. 리듀서 작성하기

//letterReducer.js
import data from "../../shared/data.json";
import uuid from "react-uuid";

// 액션 타입 정의
const ADD_LETTER = "letter/ADD_LETTER";
const UPDATE_LETTERS = "letter/UPDATE_LETTERS";

// 액션 생성자 함수
export const addLetter = (newLetter) => ({
  type: ADD_LETTER,
  payload: {
    ...newLetter,
    id: uuid(),
  },
});

export const updateLetters = (updatedLetters) => ({
  type: UPDATE_LETTERS,
  payload: updatedLetters,
});

// 초기 상태
const initialState = {
  letters: data.map((aData) => ({
    ...aData,
    id: uuid(),
  })),
};

// 리듀서
const letterReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_LETTER:
      return {
        letters: [...state.letters, action.payload],
      };
    case UPDATE_LETTERS:
      return {
        letters: action.payload,
      };
    default:
      return state;
    // return {
    //   letters: [~~, ~~~, ~~~]
    // }
  }
};

export default letterReducer;

//selectMemberReducer.js
// 액션 타입 정의
const UPDATE_SELECTED_MEMBER = "selectMember/UPDATE_SELECTED_MEMBER";

// 액션 생성자
export const updateSelectedMember = (selectedMember) => ({
  type: UPDATE_SELECTED_MEMBER,
  payload: selectedMember,
});

// 초기 상태
const initialState = {
  selectedMember: "전체보기",
};

// 리듀서
const selectMemberReducer = (state = initialState, action) => {
  switch (action.type) {
    case UPDATE_SELECTED_MEMBER:
      return {
        selectedMember: action.payload,
      };
    default:
      return state;
    // {
    //    selectedMember: "전체보기",
    // };
  }
};

export default selectMemberReducer;
  1. LetterReducer
    1) 'ADD_LETTER'와 'UPDATE_LETTERS'라는 두 가지 액션 타입을 정의함
    2) 'addLetter' 함수는 새로운 편지를 추가하며, 해당 편지에는 고유한 UUID가 부여됨
    3) 'updateLetters' 함수는 여러 편지를 한 번에 업데이트함
    4) 초기 상태는 'data.json' 파일에서 가져온 데이터를 기반으로 하며, 각 편지에는 UUID가 할당됨
    5) 리듀서는 주어진 액션에 따라 상태를 업데이트하고, 기본적으로는 현재 상태를 그대로 반환함

  2. selectMemberReducer
    1) 'UPDATE_SELECTED_MEMBER'라는 액션 타입을 정의함
    2) 초기 상태는 'selectedMember' 속성이 "전체보기"로 설정되어있음
    3) 리듀서는 'UPDATE_SELECTED_MEMBER' 액션에 대한 처리를 하고, 선택된 회원 정보를 주어진 액션의 payload로 업데이트함
    4) 기본적으로는 현재 상태를 그대로 반환하여 다른 액션에는 반응하지 않음

4. 컴포넌트 코드 수정하기

1) useContext 대신에 useSelector를 사용하여 Redux 스토어의 상태 가져오기

 const letters = useSelector((state) => state.letter.letters);

☞ useSelector를 사용하여 Redux 스토어에서 letter 리듀서의 letters 상태를 이렇게 불러 올수 있음.

2) useContext 대신에 useDispatch를 사용하여 액션을 디스패치 하기

  const deleteBtn = () => {
    const alertDelete = window.confirm("정말 삭제할래요?");
    if (alertDelete) {
      const updatedLetters = letters.filter((item) => item.id !== foundData.id);
      navigate("/");
      dispatch(updateLetters(updatedLetters));
    }
  };

☞ 이런식으로 디스패치를 하면 삭제나, 수정 등 변경이 가능함

useSelector와 useDispatch의 차이

둘의 차이는 스토어의 상태를 읽고 업데이트하는 데, 그러니까 단순하게 불러오는거는 useSelector를 사용하고 뭔가 수정을 하던 뭔가 작업이 필요하면 useDispatch를 이용해서 변경 작업을 함

그리고 완료..

  • 프로젝트명 : 쿠로미 & 마이멜로디 아티스트 팬레터함

  • 기간 : 2023. 11. 10 ~ 11. 20 (10일)

  • 프로젝트 설명 : 아티스트에게 팬레터를 작성 할 수 있는 사이트

  1. 프로젝트 기능:
  • 편지쓰기(Create)
  • 편지보기(Read)
  • 편지수정(Update)
  • 편지삭제(Delete)
  • 멤버별로 필터링 할 수 있음
  1. 사용한 기술 : react, redux, uuid, styled-components

  2. 화면 구성 :
    [Home 화면]

[Detail 화면]

profile
귀여운 걸 좋아하고 흥미가 있으면 불타오릅니다💙 최근엔 코딩이 흥미가 많아요🥰

0개의 댓글