[TIL] Redux-Toolkit 2 - Main Project

동화·2023년 2월 16일
1

TIL

목록 보기
10/21
post-thumbnail
post-custom-banner

Action → Dispatch → Reducer → Store

메인 프로젝트를 진행하면서 공부했던 리덕스 툴킷 / 내 블로그 링크
이번 메인 프로젝트 때 저장소로 이용했던
리덕스 툴킷에 대해서 프로젝트와 연결해서 자세하게 공부해 보았다.

Redux-Toolkit

효율적으로 Redux 를 이용하기 위해 더 간단하고 쉽게 만들어짐.

  • configureStore(): createStore를 감싸서 쓸만한 기본값들과 단순화된 설정을 제공/ 리듀서 조각들을 자동으로 합쳐주고, 기본 제공되는 redux-thunk를 포함해서 지정한 미들웨어들을 더해주고, Redux DevTools 확장을 사용할 수 있게 한다.
  • createReducer(): switch 문을 작성하는 대신, 액션 타입과 리듀서 함수를 연결해주는 목록을 작성하도록 함.
  • createAction(): 주어진 액션 타입 문자열을 이용해 액션 생산자 함수를 만듦. 함수 자체에 toString() 정의가 포함되어 있어서, 타입 상수가 필요한 곳에 사용가능
  • createSlice(): 조각 이름과 상태 초기값, 리듀서 함수들로 이루어진 객체를 받아 그에 맞는 액션 생산자와 액션 타입을 포함하는 리듀서 조각을 자동으로 만들어 줌.
  • createAsyncThunk: 액션 타입 문자열과 프로미스를 반환하는 함수를 받아, pending/fulfilled/rejected 액션 타입을 디스패치해주는 thunk를 생성해줌
  • createEntityAdapter: 저장소 내에 정규화된 데이터를 다루기 위한 리듀서와 셀렉터를 만들어 줌
  • createSelector 유틸리티를 Reselect 라이브러리에서 다시 익스포트해서 쓰기 쉽게 해줌



사용 방법

index.js

import { Provider } from 'react-redux';
import store from './app/store';

...
  return (
    <Provider store={store}>
      <... />
    </Provider>
  );
...

Provider store={store}
Provider로 store를 지정해준다.
store는 말 그대로 저장소이고 이 저장소 안에는 여러개의 slice들로 이루어져 있음.

configureStore

  • Reducer에서 반환된 새로운 state를 Store라는 객체로 정리해 관리하는 곳
  • Store는 Redux Toolkit configureStore에 객체 형식으로 reducer를 전달하여 만들 수 있다.
  • 기존 createStore 와 비슷하지만 > 여기서 주의할 점은 {reducer: rootReducer} 로 만들어 주어서 넣어야 함!

(property의 명이 반드시 reducer !! 그리고 createStore와 달리 ! Thunk, dev tool까지 자동 등록)

import { configureStore } from '@reduxjs/toolkit';
import goalCreateSlice from '../reducer/goalCreateSlice';

// 전역 저장소 설정
const store = configureStore({
  reducer: {
    goalCreate: goalCreateSlice,
    ...
  },
});

export default store;

먼저 스토어 생성! (const store~) [공식문서]

  1. configureStore:createStore와 달리, 여러 개의 인자 대신에 이름이 지정된 하나의 object를 받고 -> reducer을 넘겨준다

  2. Slice를 만들어줘서 action, reducer을 동시에 써 줌 (밑에)

  3. 정의한 스테이트들을 반환



createSlice

reducer 함수와 action creator 를 포함한 객체

  • name : 해당 모듈의 이름을 작성
  • initialState : 해당 모듈의 초기값 세팅
  • reducers : 리듀서를 작성. 이때 해당 리듀서의 키값으로 액션함수가 자동으로 생성
  • extraReducers : 액션함수가 자동으로 생성되지 않는 별도의 액션함수가 존재하는 리듀서를 정의

goalCreateSlice.js

import { createSlice } from '@reduxjs/toolkit';

const initGoalPrice = {
  goalName: '',
  price: '',
  monthlyPayment: '',
  url: '',
};

const initialState = { data: initGoalPrice };

// 로그인, 로그아웃 리듀서 설정 => 로그인 상태 변경 및 유저 정보 추가 or 초기화
const goalCreateSlice = createSlice({
  name: 'goalCreate',
  initialState,
  reducers: {
    setGoalCreate: (state, action) => {
      state.data = { ...state.data, ...action.payload };
    },
    setGoalCreateInit: (state) => {
      state.data = initGoalPrice;
    },
  },
});

export const { setGoalCreate, setGoalCreateInit } = goalCreateSlice.actions;

export default goalCreateSlice.reducer;

reducer을 리턴해줌으로써

슬라이스에 제공된 초기 상태 값에 대한 액세스를 제공 &
지연 상태 초기화가 제공되면 호출되고 새로운 값이 반환



useDispatch

redux의 액션 함수를 실행해서 redux store에 변경된 state값을 저장하기 위해서 useDispatch라는 리액트 훅을 사용하여 액션을 실행

dispatch를 이용 -> 액션 함수 실행 -> state저장 & 변경

useSelector

등록한 데이터를 가져와서 쓸 수 있다

Components/goalSetting.js

import { useDispatch, useSelector } from 'react-redux';
import { setGoalCreate } from '../../reducer/goalCreateSlice';


const AssetSetting = ({ goalPost }) => {
  const goalData = useSelector((state) => state.goalCreate);
  const dispatch = useDispatch();
  const setInputChange = (e) => {
    const result = {};
    result[e.target.name] = e.target.value;
    dispatch(setGoalCreate(result));
  };
  return (
    ...

pages/goalCreate.js

const GoalCreatePage = () => {
  const navigate = useNavigate();
  const dispatch = useDispatch();
  const goalData = useSelector((state) => state.goalCreate);
  const { enqueueSnackbar } = useSnackbar();

  useEffect(() => {
    dispatch(setGoalCreateInit());
  }, []);


  const goalPost = () => {
    const postdata = {
      goalName: goalData.data.goalName,
      price: goalData.data.price,
      monthlyPayment: goalData.data.monthlyPayment,
      url: goalData.data.url,
    };
    // console.log(postdata.url);

    axios
      .post(getURL_GOALS(), postdata, getWITH_TOKEN())
      .then(() => {
        Swal.fire({
          text: '목표가 등록되었어요!',
          icon: 'success',
        });
        setGoalCreateInit(); //useState 이용했던 것 
        navigate('/goalList');
      })
      .catch((error) => {
        const { message } = error;
        enqueueSnackbar(getERROR_TEXT(Number(message.slice(-3))), {
          variant: 'error',
        });
      });
  };
    
    





리덕스를 사용하지 않은 코드

pages/goalCreate.js

const GoalCreatePage = () => {
  const navigate = useNavigate();

  const [goal, setGoal] = useState(''); // 수기 목표 이름
  const [goalPrice, setGoalPrice] = useState(''); // 수기 가격
  const [monthPrice, setMonthPrice] = useState(''); // 수기 한 달 입금

  const handlerGoal = (e) => {
    setGoal(e.target.value);
  };

  const handlerGoalPrice = (e) => {
    setGoalPrice(e.target.value);
  };

  const handlerMonthPrice = (e) => {
    setMonthPrice(e.target.value);
  };

  const goalPost = () => {
    const postdata = {
      goalName: goal,
      price: goalPrice,
      monthlyPayment: monthPrice,
    };
    axios
      .post(getURL_GOALS(), postdata, getWITH_TOKEN())
      .then((response) => {
        const { data } = response;
        console.log(data);
        Swal.fire({
          text: '목표가 등록되었어요!',
          icon: 'success',
        });
        setGoal('');
        setGoalPrice('');
        setMonthPrice('');
        navigate('/goalList');
      })
      .catch((error) => {
        console.log(error);
      });
  };

  return (
    ...
post-custom-banner

6개의 댓글

comment-user-thumbnail
2023년 2월 16일

리덕스 툴킷 사용하면서도 정리를 안해놔서 머릿 속이 뒤죽박죽이었는데 이 글 보고 그나마 정리가 되네요!

답글 달기
comment-user-thumbnail
2023년 2월 17일

리덕스 툴킷쓰면서 헷갈리는 부분 많앗는데 깔끔한 정리네요 ! 메소드정리 보기쉽게 정리해주셔서 감합니다

답글 달기
comment-user-thumbnail
2023년 2월 18일

가볍게 쓰고 넘어갔지만 이번에 다시 복습합니다 ~~ 저도 조만간 리덕스 툴킷 블로깅 해야겠습니다 !

답글 달기
comment-user-thumbnail
2023년 2월 18일

저도 이번에 쓰면서도 헷갈렸는데, 다시 정리하고 갑니다!

답글 달기
comment-user-thumbnail
2023년 2월 19일

리덕스 툴킷 오랜만에 보니까 처음 보는 느낌이네요...!ㅎㅎㅠㅠ 오랜만에 복습하고 갑니다 🤗

답글 달기
comment-user-thumbnail
2023년 2월 19일

리덕스 툴킷 너무 편하죠! 좀더 사용자 측면으로 다가와준 고마운 존재랄까? 저도 맨날 쓰는 거 말고 다른 메소드를 보니 복습도 되고 좋았습니다!

답글 달기