꼭 작성해야 하는 보일러플레이트 (Boilerplate Code : 상용구 코드) 많이 요구함
ex) action, action creator, switch문 등
유용하게 사용하려면 패키지를 추가해야 함
Redux 스토어 환경 설정이 복잡
이를 개선하기 위해 RTK (Redux Toolkit) 등장!
= 짧은 코드로 같은 기능
API를 제공하고 있다
API 중 configureStore
, createSlice
사용해서 코드를 단축할 수 있다.
# NPM
npm install @reduxjs/toolkit
# Yarn
yarn add @reduxjs/toolkit
코어 redux의 createStore를 추상화한 것이다. 아래와 같이 작성한다
// store.js
import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './reducers'
const store = configureStore({ reducer: rootReducer })
const reducer = (state = [], action) => {
switch (action.type) {
case addToDo.type:
return [{ text: action.payload, id: Date.now() }, ...state];
case deleteToDo.type:
return state.filter((toDo) => toDo.id !== action.payload);
default:
return state;
}
};
immer
라이브러리 아래서 작동하므로 state에 바로 추가해도 뒤에서 알아서 새로운 state를 리턴해준다.const reducer = createReducer([], {
// 리턴안함 = {}안에 리턴 안적음 => 기존 state(push)를 mutate할 수 있음
[addToDo]: (state, action) => {
state.push({ text: action.payload, id: Date.now() });
},
// 리턴함 = {} 안씀 => 새로운 state(filter)를 리턴 할 수도 있음
[deleteToDo]: (state, action) =>
state.filter((toDo) => toDo.id !== action.payload),
});
createReducer(initialState, builderCallback)
builder
객체는 addCase, addMatcher, addDefaultCase 메서드를 제공// 1. 각 라인마다 빌더 메서드를 나누어 호출
const counterReducer = createReducer(initialState, (builder) => {
builder.addCase(increment, (state) => {})
builder.addCase(decrement, (state) => {})
})
// 2. 메서드 호출을 연결한 체이닝 형태
const counterReducer = createReducer(initialState, (builder) => {
builder
.addCase(increment, (state) => {})
.addCase(decrement, (state) => {})
})
const INCREMENT = 'counter/increment'
function increment(amount: number) {
return {
type: INCREMENT,
payload: amount,
}
}
const action = increment(3)
// { type: 'counter/increment', payload: 3 }
import { createAction } from '@reduxjs/toolkit'
const increment = createAction('counter/increment')
action = increment(3)
// returns { type: 'counter/increment', payload: 3 }
createAction
, createReducer
를 작성할 필요가 없다 !!import { configureStore, createSlice } from "@reduxjs/toolkit";
const toDos = createSlice({
name: "toDosReducer",
initialState: [],
reducers: {
add: (state, action) => {
state.push({ text: action.payload, id: Date.now() });
},
remove: (state, action) =>
state.filter((toDo) => toDo.id !== action.payload),
},
});
// console.log(toDos.reducer); // state, action
export const { add, remove } = toDos.actions;
export default configureStore({ reducer: toDos.reducer });