Redux Toolkit

redux와 사용법

Posted by 김우원 on August 20, 2023

리액트 개발을 하다보면, props가 너무 깊어져(props drilling) 전역 상태 관리를 해야할 필요가 있다.

react에서 제공하는 Context API는 사용법도 어렵고, 잘못사용하면 성능 이슈도 발생하기에 상태 관리 라이브러리 중, 현재 시장 점유율이 가장 높은 Redux에 대해 알아보자

용어 설명

  • redux-toolkit
    • redux의 주요 3가지 문제점을 개선하기 위해, redux 개발자들이 만든 패키지
      • redux는 설정이 너무 복잡하다
      • redux를 제대로 사용하기 위해서는 많은 패키지를 추가해야함
      • redux는 너무 많은 반복적 코드(boilerplate code)를 요구
  • store
    • 앱의 상태(state)와, 리듀서가 들어있는 객체
    • 보통 어플리케이션당 1개 생성
  • action
    • 상태 변화를 일으키는 객체
    • 보통 type과 data를 포함하며, 어떤 종류의 상태 변화가 필요한지를 나타냄
  • reducer
    • 이전 상태와 action을 받아 새로운 상태를 반환하는 함수
  • slice
    • redux-toolkit에서 제공하는 상태와 리듀서를 한번에 정의하는 방법

주요 사용 방법

redux store 생성 및 설정

src/app/store.js 생성. configureStore를 import하자

1
2
3
4
5
6
//app/store.js
import { configureStore } from '@reduxjs/toolkit'

export const store = configureStore({
  reducer: {},
})

그 후, index.js 을 Provider를 통해 방금 생성한 store를 prop으로 내려주고 감싼다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//index.js
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import { store } from './app/store'
import { Provider } from 'react-redux'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

Slice 생성

slice에서는 slice의 이름, 상태의 초기 값, 리듀서 함수들을 정의해야한다.

리듀서 함수란 상태를 어떻게 업데이트 할지를 정의해 두는 함수이다.

슬라이스가 생성되면, redux action creators와 리듀서 함수들을 export할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  value: 0,
};

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;

export default counterSlice.reducer;

여기서 알아두면 좋은 특징은 redux toolkit의 createSlice, createReducer는 내부적으로 Immer라는 라이브러리를 사용하고 있어서 immutable update에 신경을 덜 써도 된다.

Slice 등록

생성한 slice를 사용하기 위해서는 store에 reducer와 함께 등록해야한다.

1
2
3
4
5
6
7
8
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
})

Slice 사용

Slice를 사용하기 위해서 다음 API들을 사용해야 한다.

  • useSelector: store의 값을 읽기 위해
  • useDispatcher: action을 실행 시켜, slice의 값을 바꾸기 위해
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'

export function Counter() {
  const count = useSelector((state) => state.counter.value)
  const dispatch = useDispatch()

  return (
    <div>
      <div>
        <button
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          Increment
        </button>
        <span>{count}</span>
        <button
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          Decrement
        </button>
      </div>
    </div>
  )
}