우당탕탕 개발일기

[REDUX] 초간단한 카운터로 Redux-toolkit 연습 본문

What I Learned/etc.

[REDUX] 초간단한 카운터로 Redux-toolkit 연습

rilee 2023. 1. 10. 11:30
728x90

redux를 설치했더니 store를 생성하는 createStore에 취소선이 그어져있었다.

최신 버전의 redux가 redux-toolkit을 추천하고 redux-toolkit에서는 createStore가 사용되지 않기 때문이라고 했다.

프로젝트에서도 redux-toolkit을 쓸 예정이라, redux-toolkit을 드디어 배워보기로 했다.

redux로 골머리를 앓았던 기억이 생생하여... 😇 조금 겁이 났으나, 조금 만지작거리고나니 redux보다 훨씬 쉬운 것 같다..!

나는 붕어라서, 내가 했던 거를 기록해보려고 한다.

 


 

설치

// NPM
npm install @reduxjs/toolkit

폴더 구조는

📂 src

 |-- index.js

 |-- App.js 

 |-- store

        |-- store.js

        |-- counterSlice.js

 

 

일단 UI 먼저 구성하기

// App.js

import React, { useState } from "react";

function App() {
  const [value, setValue] = useState("");
  
  function onClickPlus() {
  	// 1씩 더하기 버튼
  }

  function onClickMinus() {
  	// 1씩 빼기 버튼
  }
  
  function onIncrease() {
  	// 입력값만큼 더하기 버튼
  }
  
  return (
    <div>
      <p>현재 숫자는 0입니다.</p>
      <button onClick={onClickPlus}>+</button>
      <button onClick={onClickMinus}>-</button>
      <div>
        <input onChange={(e) => setValue(e.target.value)}></input>
        <button onClick={onIncrease}>더하기</button>
      </div>
    </div>
  );
}

export default App;

나는 1씩 더하는 +버튼, 1씩 빼는 -버튼, input에 숫자 입력한만큼 더해주는 버튼 총 세가지를 만들었다.

변수명도 막 지은 진짜 초초초간단 컴포넌트

 

Slice 정의하기

// counterSlice.js

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

let initialState = {
  now: 0
};

const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    plus: (state, action) => {
      // 1씩 증가하기
      state.now += 1;
    },
    minus: (state, action) => {
      // 0 이상일 때, 1씩 감소하기
      if (state.now > 0) state.now -= 1;
    },
    plusInput: (state, action) => {
      // 입력값만큼 증가시키기
      state.now += Number(action.payload);
    }
  }
});

export const counterActions = counterSlice.actions; // dispatch 할 때 사용할 actions export
export default counterSlice;

initialState를 정의해주기. (현재값이라는 뜻으로 변수명을 'now'로 했다.)

counterSlice를 정의해주면 되는데, 이 때 counterSlice에는 name, initialState, reducers를 필수로 가져야한다.

 

store 만들기

// store.js 

import { configureStore } from "@reduxjs/toolkit";
import counterSlice from "./counterSlice";

const store = configureStore({
  // 여기는 단수형태인 'reducer'!
  reducer: {
    counter: counterSlice.reducer
  }
});

export default store;

store에는 reducer가 필요하므로 import 해 온 counterSlice.reducer를 counter라는 이름으로 넣어줌.

다른 이름의 파일로 slice가 만들어지면 저기다가 추가로 넣어주어야함.

productSlice라는 파일이 생기고 그 안에 createSlice해주면, (변수): productSlice.reducer 이렇게 추가!

 

index 파일에 Provider로 감싸주기

// index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

// Provider와 Provider에 연결해줄 store import
import { Provider } from "react-redux";
import store from "./store/store";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  // store라는 이름으로 import 해 온 store 넣어주기
  <Provider store={store}> 
    <App />
  </Provider>
);

...

Provider는 state를 어떤 컴포넌트들에게 제공할 지를 정하는 울타리.

상태 관리는 전역적으로 가능해야하니까 최상단 파일(index)에서 Provider로 감싸주기! 그래야 어디에서든 reducer를 쓸 수 있다.
이 때, store를 반드시 정의해주어야 해당 범위 안에서 store에 있는 reducer들을 사용할 수 있다.

 

dispatch 사용하기

// App.js

import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { counterActions } from "./store/counterSlice";

function App() {
  const [value, setValue] = useState("");

  const number = useSelector((state) => state.counter.now); // 뭘 넣어야할지 잘 모르겠으면 콘솔 찍어보기!
  const dispatch = useDispatch();

  function onClickPlus() {
    dispatch(counterActions.plus());
  }

  function onClickMinus() {
    dispatch(counterActions.minus());
  }

  function onIncrease() {
    dispatch(counterActions.plusInput(value));
  }
  return (
    <div>
      <p>현재 숫자는 {number}입니다.</p>
      <button onClick={onClickPlus}>+</button>
      <button onClick={onClickMinus}>-</button>
      <div>
        <input onChange={(e) => setValue(e.target.value)}></input>
        <button onClick={onIncrease}>더하기</button>
      </div>
    </div>
  );
}

export default App;

counterSlice.js에서 export했던 counterActions를 import 해와서, action type 즉 slice의 reducers에서 함수로 정의했던 action type들을 불러오면 dispatch끝!

개인적으로 이 부분이 제일 심플해서 좋았다!

728x90