[React] Redux Toolkit 사용하기

@eunjios·2023년 10월 18일
3

Redux

목록 보기
2/3
post-thumbnail

Redux Toolkit

React에서 Redux Toolkit 사용하기

Setting

CRA

// npx
npx create-react-app .

// npm
npm init react-app .

// yarn
yarn create react-app .

Redux Toolkit 및 react-redux 설치

// npm
npm install @reduxjs/toolkit react-redux

// yarn
yarn add @reduxjs/toolkit react-redux

만약 해당 위치에 이미 redux를 설치한 경우 package.json 파일로 가서 redux dependencies 를 지워줘야 한다.


카운터 예제

0. Counter 컴포넌트 만들기

카운터 값과 더하기 빼기 버튼이 있는 컴포넌트를 만들자. 당연히 지금은 아무 동작도 하지 않는다.

components/Counter.js

const Counter = () => {
  const counter = 0;

  return (
    <div>
      <h2>{counter}</h2>
      <div>
        <button>더하기</button>
        <button>빼기</button>
      </div>
    </div>
  );
};

1. store 만들기

const store = configureStore({
  reducer: {리듀서 map},
});

store는 위와 같이 configureStore 를 사용해서 만들 수 있다.

Redux Toolkit를 사용하는 경우도 리액트 앱 하나에 하나의 store만 존재해야 한다.


store/index.js

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

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

export default store;

여기서 reducer는 별도의 슬라이스를 만들어서 구현할 수 있다. 일단은 빈 객체로 두자.


2. 슬라이스 만들기

const slice = createSlice({
  name: slice이름,
  initialState: state초기값,
  reducers: {
    // 리듀서구현
  },
});

슬라이스는 store의 조각이라고 생각하면 된다. 위와 같이 createSlice 를 사용해서 만들 수 있다. 여러 슬라이스는 configureStore 를 통해 하나의 store에 저장된다.

Redux Toolkit를 사용하지 않고 Redux 만을 사용해서 리듀서를 구현했을 때는 기존 state를 직접적으로 변경해서는 안 되고 새로운 객체로 반환해야 했다. 하지만 Redux Toolkit를 사용하면 리듀서 내부에 state를 직접 변경하는 코드를 작성해도 된다. (state.counter++; 사용 가능) 이는 Redux Toolkit 내부적으로 새로운 객체를 만들어서 반환하기 때문에 가능한 것이다.


store/counter.js

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

const initialState = {
  counter: 0,
}

export const counterSlice = create({
  name: 'counter',
  initialState,
  reducers: {
    add: (state, action) => {
      state.counter += action.payload;
    },
    sub: (state, action) => {
      state.counter -= action.payload;
    },
  }
});

export const counterActions = counterSlice.actions;
export default couterSlice.reducer; 
  • Redux Toolkit를 사용하면 리듀서 내부에서 state.counter 값을 직접적으로 바꿀 수 있다.
  • action.payloadcounterSlice 의 actions 을 dispatch 할 때 넘기는 인수를 말한다.

아까 비워두었던 storereducer 에 방금 counterSlice 에서 정의한 리듀서 함수를 등록하자.

store/index.js

import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counter';

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

export default store;
  • store/counter.js 에서 counterSlice.reducer 를 default로 export 했기 때문에 여기서 counterReducer 는 store/counter.js 의 counterSlice.reducer 가 된다.

3. 컴포넌트에서 store의 state 접근하기

const state = useSelector(state => state.슬라이스key.해당슬라이스의state);

Redux toolkit도 useSelector 를 사용해서 store의 특정 state에 접근할 수 있다. 콜백 함수의 반환값에 접근하는 것이다.


component/Counter.js

import { useSelector } from 'react-redux';

const Counter = () => {
  const counter = useSelector(state => state.counter.counter);

  return (
    <div>
      <h2>{counter}</h2>
      <div>
        <button>더하기</button>
        <button>빼기</button>
      </div>
    </div>
  );
};
  • useSelector 의 콜백함수를 통해 state.countercounterReducer 에 접근하고, state.counter.countercounterSlice 의 state 중 counter를 가져온다.

4. 컴포넌트에서 store의 action 접근하기

const dispatch = useDispatch();
dispatch(액션.리듀서함수(payload));

Redux toolkit도 역시 useDispatch 를 사용해서 store의 특정 action에 접근할 수 있다. 여기서 리듀서함수의 인자는 action.payload 로 접근한다.


component/Counter.js

import { useSelector, useDispatch } from 'react-redux';
import { counterActions } from '../store/counter';

const Counter = () => {
  const counter = useSelector(state => state.counter.counter);
  const dispatch = useDispatch();
  
  const addHandler = () => {
    dispatch(counterActions.add(10));
  };
  
  const subHandler = () => {
    dispatch(counterActions.sub(10));
  };

  return (
    <div>
      <h2>{counter}</h2>
      <div>
        <button onClick={addHandler}>더하기</button>
        <button onClick={subHandler}>빼기</button>
      </div>
    </div>
  );
};
  • dispatch(counterActions.add(10)) 의 10은 리듀서에서 action.payload로 접근할 수 있다.

5. store 제공하기

<Provider store={store}>
  <App />
</Provider>

Redux Toolkit도 동일하게 최상위 컴포넌트를 Provider 로 감싸서 store를 제공해야 한다. 이렇게 감싸면 내부 컴포넌트는 리덕스의 store를 전역적으로 사용할 수 있다.


index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

import { Provider } from 'react-redux';
import store from './store';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

References

profile
growth

0개의 댓글