[React] 🔮Redux Toolkit 사용법

TATA·2023년 2월 27일
0

React

목록 보기
15/32

▷ Redux Toolkit이란?

RTK

Redux를 편하게 사용하기 위한 리덕스 공식 개발 도구이다.
RTK는 saga를 제외한 나머지 라이브러리를 따로 설치하지 않고 사용할 수 있게 해준다.

라이브러리 종류
redux-actions : 많아지는 액션을 관리
immer : 상태값의 불변성 보존
reselect : store값을 효율적으로 핸들링하여 불필요한 리렌더링을 막아줌
redux-thunk : 액션을 비동기적으로 만들 수 있음
redux-saga


🔮 설치

# toolkit 설치
npm install @reduxjs/toolkit react-redux

🔮 Store 연동하기

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

/* Provider 가져오기 */
import { Provider } from "react-redux";
import store from "./store/count";

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

🔮 configureStore

combineReducers로 리듀서들을 모아두지 않고,
reducer속성 안에 리듀서 함수를 넣어주면 된다.

/* configureStore 가져오기 */
import { configureStore } from "@reduxjs/toolkit";
import { counterSlice } from "../reducers/countReducer";
import { logger } from "redux-logger";
...

export const store = configureStore({
  reducer: {
    counter: counterSlice.reducer,
  },
  // 사용할 미들웨어 배열
  // 기본 미들웨어를 무시하고 사용자 정의 미들웨어만 적용하고 싶다면 ▹ middleware: [thunk, logger],
  middleware : (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
  
  // 개발자 도구를 사용할 것인지(boolean) 디폴트 값은 true이다.
  devTools : process.env.NODE_ENV !== 'production',
  
  // 초기 state
  preloadedState,
  
  // enhancer 배열(middleware가 적용되는 순서보다 앞서서 추가하고 싶을 때 사용)
  enhancers : [batchedSubscribe, ...defaultEnhancers],
});
 

🔮 createSlice

createSlice는 액션에 대한 함수 설정과
리듀서를 따로 생성하지 않아도 된다.

import { createSlice } from '@reduxjs/toolkit'

const initialState = {
  name: "TATA",
  value: 0,
};

export const counterSlice = createSlice({
  name: 'counter', // 이름
  initialState, // 초기값
  reducers: {                 // 리듀서는 액션 하나하나 모여서 구성
    increase: (state) => {
      state.value++;
    },
    decrease: (state) => {
      state.value--;
    },
    changeName: (state, action) => {
      state.name = action.payload;
    },
    changeAll: (state, action) => {
      return {...state, ...action.payload};
    },
  },
})

// action 내보내는 방법
export const { increase, decrease, changeName } = counterSlice.actions;

// slice는 slice.reducer로 내보낸다.
export default counterSlice.reducer; 

🔮 useSelector, useDispatch로 상태 접근

useSelector: 스토어에서 현재 상태 값을 가져오기
useDispatch: 변경되는 값을 스토어로 전달

/* Count.js */
import { useSelector, useDispatch } from "react-redux";
import { decrease, increase, changeName, changeAll } from "../reducer/counter";

const Count = () => {
  const { name, value } = useSelector((state) => state.counter);
  const dispatch = useDispatch();

  const changeNameFunc = () => {
    dispatch(changeName("Chimmy"));
  };

  const changeAllFunc = () => {
    dispatch(changeAll({ name: "BT21", value: 7 }));
  };

  return (
    <>
      <h2>Name {name}</h2>
      <span>Count: {value}</span>
      <button onClick={() => dispatch(increase())}>+</button>
      <button onClick={() => dispatch(decrease())}>-</button>
      <button onClick={changeNameFunc}>changeName</button>
      <button onClick={changeAllFunc}>changeAll</button>
    </>
  );
};

export default Count;

비동기 작업 함수 작성

🔮 createAsyncThunk

기존의 react-thunk 사용 방식으로는 slice로 구현한 state를 변경할 수 없다.
toolkit에서 제공하는 createAsyncThunk로 비동기 작업을 구현해야 한다.

createAsyncThunk(type, payloadCreator, options)

/*
* type: 해당 요청의 타입
*       (pending, fulfilled, rejected가 알아서 상황에 맞게 붙여짐)
* 
*       pending: 대기
*       fulfilled: 이행 => payload로 보내짐
*       rejected: 실패 => action.error로 보내짐
*
*------------------------
*
* payloadCreator: 비동기 함수 실행 부분(인자 두개를 받음)
*
*            arg: 첫번째 파라미터(생략가능)
*                 실행하고자 하는 비동기 함수를 구성하는데 사용될 사용자 입력으로 활용
*
*       thunkAPI: dispatch, getState, rejectWithValue, 
*                 fulfillWithValue 등의 함수를 실행 할수 있는 API 묶음
*/

🔮 thunk 함수 만들기

/* createAsyncThunk 가져오기 */
import { createAsyncThunk } from "@reduxjs/toolkit";

// thunk 함수 만들기
const userThunk = createAsyncThunk(
  "user/userThunk",
  async (thunkAPI) => {
  try {
    const res = axios.get("https://..../user");
    return res.data;
  } catch (error) {
    return thunkAPI.rejectWithValue(error);
  }
});

🔮 extraReducer

Redux에서는 자체적으로 비동기 처리를 지원하지 않아서,
extraReducers를 사용해 Thunk함수를 등록시켜주어야 한다.

const initialState = {
  loaging: false,
  data: [],
  error: null,
}

export const userSlice = createSlice({
  name: "userReducer",
  initialState,
  extraReducers: (builder) => {
    builder
      .addCase(userThunk.pending, (state, action) => {
        state.loading = true;
      })
      .addCase(userThunk.fulfilled, (state, action) => {
        state.loading = false;
        state.data = action.payload;
      })
      .addCase(userThunk.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error;
      })
  }
})

/*
* extraReducer에 파라미터인 builder를 통해
* addCase로 case(pending, fulfilled, rejected)를 등록시켜준다.
*/



☂️ Redux로 전역상태 관리하는 방법 보러가기
👉 React Toolkit 잘 정리된 블로그1
👉 Redux Toolkit 잘 정리된 블로그2
👉 Redux Toolkit 잘 정리된 블로그3
👉 (공식문서)configureStore createReducer createSlice createAsyncThunk

profile
🐾

0개의 댓글