Redux Toolkit

최현호·2022년 7월 27일
0

Redux

목록 보기
6/6
post-thumbnail

Redux Toolkit

https://redux-toolkit.js.org/

사용하는 이유

Redux Toolkit은 Redux를 더 사용하기 쉽게 만들기 위해 Redux에서 공식 제공하는 개발도구 Redux Toolkit은 아래와 같은 Redux의 문제점을 보완하기 위해 등장 하였습니다.


기존 리덕스의 문제

  • 저장소 구성의 복잡성
  • 많은 패키지 필요성(의존성) + 미들웨어 등..
  • 한 작업 시 필요한 수 많은 코드양(boilerplate)

Redux Toolkit 설치

npm
npm install @reduxjs/toolkit

yarn
yarn add @reduxjs/toolkit

기존 redux 를 이용한 카운터

import './App.css';
import { createStore } from 'redux';
import { useSelector } from 'react-redux'; // useSelector 를 통해 카운터가 스토어의 value 값을 가져온다
import { Provider } from 'react-redux'; //  provider 를 통해 애플리케이션에 공급
import { useDispatch } from 'react-redux' // 버튼을 눌렀을 때 state 값을 바꾸는 dispatch 


// 초기값
const initialState = {value : 0};

// 스토어
const store = createStore(reducer, initialState);

// 리듀서
function reducer(state, action){
  if(action.type === 'up'){
    return {...state, value : state.value + action.step} 
    // 불변하게 코드를 다루기 위해 기존의 코드를 복제 ({...state} 부분)
  }
  return state;
}

// 버튼을 누르면 숫자가 증가하는 카운터
function Counter(){
  const dispatch = useDispatch();
  const count = useSelector(state => state.value)
  return (
    <div>
      <button onClick={()=>{
        dispatch({type : 'up', step : 2}); 
      }}>+</button>{count}
    </div>
  )
}


function App() {
  return (
    <Provider store={store}>
      <div>
        <Counter></Counter>
      </div>
    </Provider>
  );
}

export default App;

지금까지는 하나의 store 안에 모든 정보를 담았다.

하지만 프로그램이 커지면 기능별로 작은 스토어를 만들고 싶어질수 있습니다.
이러한 작은 스토어를 slice 라고 부르겠습니다.

그러면 작은 스토어들을 합쳐서
리덕스 툴킷이 리덕스가 요구하는 큰 스토어로 알아서 만들어 줍니다.


카운터라는 기능을 위한 - slice

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

const counterSlice = createSlice({
  name : 'counter', // 슬라이스의 이름
  initialState : {value : 0}, // 스토어는 초기 값이 필요
  reducers : {
    up : (state, action) => {
      state.value = state.value + action.payload; 
      // up 타입일 때 처리해야하는 리듀서 (dispatch 역할)
    }
  }
});
  • 위와 같은 작은 slice 를 모아서 하나의 큰 스토어로 만들때는 configureStore 사용

하나의 큰 스토어 - configureStore

const store = configureStore({
  // 객체를 전달하고 필수적으로 reducer 전달
  reducer : {
    counter : counterSlice.reducer 
    // up을 포함하여 counterSlice 안에 들어있는 리듀서 여러가지들을 하나로 해준다.
  }
}) 
  • counterSlice 안에 있는 리듀서들이 있다면, 즉 up 말고 down 이나 여러가지가 있을 수 있는데 이것들을 하나로 합쳐서 하나로 만든 리듀서를 자동으로 만들어줍니다.
  • 그렇게 만들어진 리듀서가 counter

useSelector 사용

const count = useSelector(state => state.value) // 기존 리덕스의 useSelector

const count = useSelector(state => {
    return state.counter.value // 0
  // count 값은 counterSlice의 전달한 value 초기값
  }) 

dispatch 사용

function Counter(){
  const dispatch = useDispatch();
  //const count = useSelector(state => state.value) // 기존 리덕스의 useSelector
  const count = useSelector(state => {
    return state.counter.value // count 값은 counterSlice의 전달한 value 초기값
  }) 

  return (
    <div>
      <button onClick={()=>{
        // dispatch({type : 'up', step : 2}); 기존 리덕스
        dispatch(counterSlice.actions.up(2)) 
      }}>+</button>{count}
    </div>
  )
}

전체 코드

import './App.css';
import { createStore } from 'redux';
import { useSelector } from 'react-redux'; // useSelector 를 통해 카운터가 스토어의 value 값을 가져온다
import { Provider } from 'react-redux'; //  provider 를 통해 애플리케이션에 공급
import { useDispatch } from 'react-redux' // 버튼을 눌렀을 때 state 값을 바꾸는 dispatch 

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

const counterSlice = createSlice({
  name : 'counter', // 슬라이스의 이름
  initialState : {value : 0}, // 스토어는 초기 값이 필요
  reducers : {
    up : (state, action) => {
      state.value = state.value + action.payload;
    }
  }
});

const store = configureStore({
  // 객체를 전달하고 필수적으로 reducer 전달
  reducer : {
    counter : counterSlice.reducer 
    // up을 포함하여 counterSlice 안에 들어있는 리듀서 여러가지들을 하나로 해준다.
  }
}) 

function Counter(){
  const dispatch = useDispatch();
  //const count = useSelector(state => state.value) 기존 리덕스의 useSelector
  const count = useSelector(state => {
    return state.counter.value // count 값은 counterSlice의 전달한 value 초기값
  }) 

  return (
    <div>
      <button onClick={()=>{
        // dispatch({type : 'up', step : 2}); 기존 리덕스
        dispatch(counterSlice.actions.up(2)) 
      }}>+</button>{count}
    </div>
  )
}


function App() {
  return (
    <Provider store={store}>
      <div>
        <Counter></Counter>
      </div>
    </Provider>
  );
}

export default App;

참고

profile
현재 블로그 : https://choi-hyunho.com/

0개의 댓글