리덕스를 사용하기 위해 작성한 ducks 패턴의 요소로 코드 양이 많아지는 부분을 개선하기 위해 나온 패키지이다.
리덕스 툴킷은 코드를 더 적게 쓰면서 리덕스를 더 편하게 쓰기 위한 기능들이 갖춰져 있다. 기존 리덕스와 다른 점은 모듈을 만드는 부분이 좀 다르다.
기존에 사용한 redux 모듈 코드
기존에 사용한 counter 모듈은 휴먼 에러를 방지하기 위해
액션 value와 액션 creator를 모두 작성했다.
또한 dispatch를 할 때 액션 타입이 지정된 액션 creator를
호출함으로써 상태값을 업데이트 할 수 있었다.
counter.js
//액션 value
const ADDED = 'counter/added';
const SUBSTRACTED = 'counter/substracted';
const ADDED_N = 'counter/added_n';
const SUBSTRACTED_N = 'counter/substracted_n'
//초기값 설정
const initialState = {
number: 0
};
//액션 creator
export const addedN = (payload) => {
return {
type: ADDED_N,
payload
}
}
export const subtractedN = (payload) => {
return {
type: SUBSTRACTED_N,
payload
}
}
//리듀서 함수 작성
const counter = (state = initialState, action) => {
switch (action.type) {
case ADDED:
return { number: state.number + 1 };
case SUBSTRACTED:
return { number: state.number - 1 };
case ADDED_N:
return { number: state.number + action.payload };
case SUBSTRACTED_N:
return { number: state.number - action.payload };
default:
return state;
}
};
export default counter;
이제 redux-toolkit으로 코드를 변경해보자.
yarn add @reduxjs/toolkit
또는 npm install @reduxjs/toolkit
configStore.js
리덕스 툴킷으로 스토어를 구상할 때 configureStore 메서드를 이용한다. (툴킷에 포함된 API)
import { configureStore } from '@reduxjs/toolkit';
import counter from '../modules/counter';
const store = configureStore({
reducer:{
counter // => counter:counter 생략
}
})
export default store;
기존 redux에서 스토어 구상했을 때
//기본 리듀서
const rootReducer = combineReducers({
//생성된 리듀서들을 넣어줌
counter
});
const store = createStore(rootReducer);
➡️ 기존 redux에는 combineReducers,createStore로 2가지 API를 사용한 반면, 툴킷으로는 1개의 API로 이용할 수 있다.
createSlice
API는 액션 creator와 reducer를 가지고 있어 한번에 생성할 수 있다.
인자로는 name,initialState,reducers를 가진다.
counter 리듀서에 숫자 증가/감소를 추가해보자.
counter.js
import { createSlice } from '@reduxjs/toolkit';
//초기값 설정
const initialState = {
number: 0
};
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
addNumber: (state, action) => {
state.number = state.number + action.payload;
},
minusNumber: (state, action) => {
state.number = state.number - action.payload;
}
}
});
//리듀서를 바깥으로 내보냄
export default counterSlice.reducer;
export const { addNumber, minusNumber } = counterSlice.actions;
리듀서들은 여러개가 들어갈 수 있어 객체 형태로 만든다. 숫자 증가/감소하는 액션(addNumber,minusNumber)을 key에 적고 value는 함수로 작성한다.
reducers 안에 있는 key들이 액션 creator에 해당되며
counterSlice.actions를 통해 액션들을 밖으로 내보낼 수 있다.
➡️ counterSlice.actions,counterSlice.reducer을 통해
액션 creator과 reducer를 모두 내보낸다.
todos.js
기존 redux에서는 액션 value/creator,reducer를 따로따로 만든 반면, createSlice API를 통해 한번에 정의할 수 있다.
import { createSlice } from "@reduxjs/toolkit";
import { v4 as uuidv4 } from "uuid";
const initialState = [
{
id: uuidv4(),
title: "리액트 공부하기",
contents: "빨리빨리 암기하기",
isDone: false,
},
{
id: uuidv4(),
title: "스프링 공부하기",
contents: "인강 열심히 들어보기!!",
isDone: true,
},
{
id: uuidv4(),
title: "데이트",
contents: "홍대입구역에서 3시까지",
isDone: false,
},
];
const todosSlice = createSlice({
name: 'todos',
initialState,
reducers: {
addTodo: (state, action) => {
return [...state, action.payload];
},
removeTodo: (state, action) => {
return state.filter(item => item.id !== action.payload);
},
switchTodo: (state, action) => {
return state.map(item => {
if (item.id === action.payload) return { ...item, isDone: !item.isDone };
return item;
})
}
}
})
export default todosSlice.reducer;
export const { addTodo, removeTodo, switchTodo } = todosSlice.actions;
리액트는 불변성을 유지해야하기 때문에 할일을 추가하거나 삭제할 때 새로운 배열로 반환해야한다.
그러나 redux-toolkit에는 immer 기능이 있어 state.push(action.payload)를 작성해도 알아서 할일이 추가된 새로운 배열을 반환해준다.
기존 state 상태와 특정 액션이 일어났을 때
그 액션이 무엇이며, state가 어떻게 변경되는지 확인할 수 있다. redux-toolkit에 Devtools가 내장되어 있어
구글 웹스토어에서 플로그인을 설치하면 바로 이용할 수 있다.
👉 아래 링크를 통해 바로 설치할 수 있다.