FrontEnd/React 심화

[React] Redux Toolkit 사용법

기은P 2022. 9. 19. 15:23
반응형

1. 개요

React에서 상태관리 툴로 Redux를 사용하는데, Redux를 사용하기가 상당히 까다롭고 진입장벽이 높습니다.

액션 함수, 액션 생성 함수, 리듀서, 스토어... 또 타입스크립트를 쓰게 되면 해당 타입을 또 일일히 지정해주어야 하고 관리할 상태값이 1개가 생길 때마다 작성하는 코드도 많아집니다. 가독성도 안좋아지고요...

이러한 문제 때문에 상태관리를 도와주는 라이브러리가 등장하게 되었는데, 사실 Redux Toolkit보다 더 직관적이고 좋은 라이브러리는 많습니다.

다만 상태관리라는 개념에 대해 정확하게 알고 사용하는 것이 좋을 것이라고 생각이 되어 Redux를 먼저 사용해보고 그 Redux를 편리하게 만든 Redux Toolkit에 알아보려고 합니다!

 

 

 

 

2. 설치

공식사이트는 아래와 같습니다.

https://redux-toolkit.js.org/introduction/getting-started 

npm install @reduxjs/toolkit react-redux

공식 사이트에 나온 것처럼 프로젝트에 위 패키지를 설치해 줍니다!

 

 

 

3. 주요 함수 및 실제 사용 코드

리덕스 툴킷을 사용할 때 2개의 함수만 잘 사용하시면 됩니다.

실제 리듀서가 동작하는 createSlice(), store의 구성설정인 configureStore().

아이러니하게도 기능 압축이 잘 된 라이브러리인데, 공식 사이트의 설명이 조금 난해하게 되어 있습니다.

요점만 잘 이해하기 위해서 함수별로 정리해보겠습니다.

 

3-1.createSlice()

/store/counterSlice.ts

import { createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'

interface CounterState {
  value: number
}

const initialState = { value: 0 } as CounterState

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

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

코드는 타입스크립트로 작성되었습니다. 자바스크립트로 된 버전은 공식사이트를 참고해주세요.

 

위 코드는 카운트를 증감하는 예제입니다.

createSlice함수는 파라미터에 name, initialState, reducers 이 3개를 작성해주면 됩니다.

 

1) initialState: default값이면서 동시에 상태 관리에 사용되는 type입니다.

interface로 type을 지정하고, initalState의 값을 초기화를 시켜주는데, 카운터 예제이기 때문에 초기값을 0으로 설정한 것을 확인할 수 있습니다.

 

2) name: createSlice()를 통해 slice를 생성하게 되는데, 내부적으로 중복을 피하기 위해서 사용되는 고유한 값입니다.

 

3) reducers: 상태 변화를 처리하는 함수를 정의합니다. 함수의 이름은 dispatch로 부르는 액션 함수의 이름이며, 함수 내부는 위와 같이 state의 상태 값을 변경하는 처리를 해줍니다. dispatch에 포함해서 전달한 값은 PayloadAction<>의 타입의 action.payload 값으로 확인할 수 있습니다.

기존의 Redux에서 액션 타입을 지정하고, 타입에 따른 액션 생성함수, action.type에 따른 상태 변화 처리 및 불변성 처리를 3단계에 나눠서 했었다면, Redux Toolkit에서는 이 하나의 함수를 정의하는 것으로 끝납니다!

 

4) 후처리: createSlice로 생성된 counterSlice의 actions를 export시켜 외부에서 action을 호출할 수 있게 합니다. reducer 또한 export시켜 추후에 store에 리듀서를 등록할 수 있도록 노출시켜 줍니다.

 

 

3-2. configureStore()

/store/store.ts

import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../store/counterSlice'

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

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch

3-1에서 내보낸 reducer를 configureStore에 등록시켜 줍니다. 추후에 App에서 state.counter.value를 사용해 store에 저장된 리듀서의 값을 가져올 수 있습니다.

 

 

3-3. App 전역 Provider에 등록

// index.tsx
import {Provider} from "react-redux"
import {store} from './store/store'

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

위에서 작성한 store를 전역에서 사용할 수 있도록 React의 App 시작점에 Provider로 등록을 해줍니다.

 

 

3-4. Store 호출

import React from 'react'
import type { RootState } from '../../app/store'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './store/counterSlice'

export function Counter() {
  const count = useSelector((state: RootState) => 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>
  )
}

useSelector Hooks를 이용해 store에 저장된 state를 가져오고, useDispatch를 사용해 변경할 값을 reducer에 전달해줍니다.

일반 Redux보다 Redux Toolkit으로 사용한 코드가 훨씬 더 직관적입니다!

 

 

 

4. 온라인에서 실제로 해보기

https://codesandbox.io/s/github/reduxjs/redux-essentials-counter-example/tree/master/?from-embed 

 

redux-essentials-counter-example - CodeSandbox

redux-essentials-counter-example using @reduxjs/toolkit, @testing-library/jest-dom, @testing-library/react, @testing-library/user-event, react, react-dom, react-redux, react-scripts

codesandbox.io

 

반응형