aotoyae

[React] Redux toolkit : store 만들기 본문

React

[React] Redux toolkit : store 만들기

aotoyae 2024. 2. 16. 20:02

 

 

💡 toolkit 을 이용해서 store 를 다른 방식으로 만들어보자!

 

먼저 npm install @reduxjs/toolkit ~

 

✳️ 카운터 기능

configStore.js

// import { combineReducers, createStore } from "redux";
import counter from "../modules/counter";
import { configureStore } from "@reduxjs/toolkit";

// const rootReducer = combineReducers({ counter });
// const store = createStore(rootReducer);

const store = configureStore({ reducer: { counter } });

export default store;

 

주석 처리 해둔 곳이 원래 쓰던 일반 리듀서 방식!

기존엔 API 두 개가 필요했지만 이제 configureStore 하나만 있어도 된다!

 

App.js

기존 방식과 같다.

import "./App.css";
import { useDispatch, useSelector } from "react-redux";
import { plusNumber, minusNumber } from "./store/modules/counter";

function App() {
  const counter = useSelector((state) => state.counter);
  const { number } = counter;

  const dispatch = useDispatch();

  const onPlusNumber = () => {
    dispatch(plusNumber(1));
  };

  const onMinusNumber = () => {
    dispatch(minusNumber(1));
  };

  return (
    <div>
      <h1>toolkit</h1>
      <div>
        <h2>{number}</h2>
        <button onClick={onPlusNumber}>+</button>
        <button onClick={onMinusNumber}>-</button>
      </div>
    </div>
  );
}

export default App;

 

기존 리덕스 방식 counter.js

const PLUS_NUMBER = "plus_number";
const MINUS_NUMBER = "minus_number";

// Action Creater
export const plusNumber = (payload) => {
  return {
    type: PLUS_NUMBER,
    payload
  };
};

export const minusNumber = (payload) => {
  return {
    type: MINUS_NUMBER,
    payload
  };
};

// Initial State
const initialState = {
  number: 0,
};

// Reducer
const counter = (state = initialState, action) => {
  switch (action.type) {
    case PLUS_NUMBER:
      return { number: state.number + action.payload }; // number 에 넘어온 payload 만큼 더함
    case MINUS_NUMBER:
      return { number: state.number - action.payload }; // number 에 넘어온 payload 만큼 뺌
    default:
      return state;
  }
};

export default counter

 

 

Toolkit 방식 counter.js

createSlice API 사용 : action creater & reducer 한 번에 생성!

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

const initialState = {
  number: 0,
};

const counterSlice = createSlice({ // 카운터 슬라이스에 액션크리에이터 & 리듀서 모두를 담는다.
  name: "counter",
  initialState,
  reducers: { // ** reducers 오타 주의
    plusNumber: (state, action) => {
      state.number += action.payload;
    },
    minusNumber: (state, action) => {
      state.number -= action.payload;
    },
  },
});

export default counterSlice.reducer; // 리듀서 내보냄
export const { plusNumber, minusNumber } = counterSlice.actions; // 액션크리에이터 내보냄

 

✳️ 투두리스트

기존 todos.js

import { v4 as uuidv4 } from "uuid";

action items
const ADD_TODO = "ADD_TODO";
const REMOVE_TODO = "REMOVE_TODO";
const SWITCH_TODO = "SWITCH_TODO";

export const addTodo = (payload) => {
  return {
    type: ADD_TODO,
    payload,
  };
};

export const removeTodo = (payload) => {
  return {
    type: REMOVE_TODO,
    payload,
  };
};

export const switchTodo = (payload) => {
  return {
    type: SWITCH_TODO,
    payload,
  };
};

// initial states
const initialState = [
  {
    id: uuidv4(),
    title: "리액트 공부하기",
    contents: "빨리빨리 암기하기",
    isDone: false,
  },
  {
    id: uuidv4(),
    title: "스프링 공부하기",
    contents: "인강 열심히 들어보기!!",
    isDone: true,
  },
  {
    id: uuidv4(),
    title: "데이트",
    contents: "홍대입구역에서 3시까지",
    isDone: false,
  },
];

reducers
const todos = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TODO: // 기존의 배열에 입력받은 객체를 더함
      return [...state, action.payload];
    case REMOVE_TODO: // 기존의 배열에서 입력받은 id의 객체를 제거(filter)
      return state.filter((item) => item.id !== action.payload);
    case SWITCH_TODO: // 기존의 배열에서 입력받은 id에 해당하는 것만 isDone을 반대로 변경(아니면 그대로 반환)
      return state.map((item) => {
        if (item.id === action.payload) {
          return { ...item, isDone: !item.isDone };
        } else {
          return item;
        }
      });
    default:
      return state;
  }
};

export default todos;

 

Toolkit 방식 todos.js

import { createSlice } from "@reduxjs/toolkit";
import { v4 as uuidv4 } from "uuid";

// initial states
const initialState = [
  {
    id: uuidv4(),
    title: "리액트 공부하기",
    contents: "빨리빨리 암기하기",
    isDone: false,
  },
  {
    id: uuidv4(),
    title: "스프링 공부하기",
    contents: "인강 열심히 들어보기!!",
    isDone: true,
  },
  {
    id: uuidv4(),
    title: "데이트",
    contents: "홍대입구역에서 3시까지",
    isDone: false,
  },
];

const todosSlice = createSlice({
  name: "todos",
  initialState,
  reducers: {
    addTodo: (state, action) => {
      return [...state, action.payload];
    },
    removeTodo: (state, action) => {
      return state.filter((item) => item.id !== action.payload);
    },
    switchTodo: (state, action) => {
      return state.map((item) => {
        if (item.id === action.payload) {
          return { ...item, isDone: !item.isDone };
        } else {
          return item;
        }
      });
    },
  },
});

export default todosSlice.reducer;
export const { addTodo, removeTodo, switchTodo } = todosSlice.actions;

 

코드가 굉장히 짧아졌다!