리덕스 툴킷에 대해 알아보고, 저번에 배운 내용에 적용을 해봤다.
Redux Store
툴킷을 적용하기 전의 store의 코드는 아래와 같다.
// configStore.js
import {createStore} from "redux";
import {combineReducers} from "redux";
import counter from "../modules/counter";
// 여러개의 리듀서를 하나로 모은다.
const rootReducer = combineReducers({
counter: counter,
});
// 만든 리듀서를 통해 store를 생성.
const store = createStore(rootReducer);
// 생성한 리듀서를 export(내보낸다.)
export default store;
툴킷을 적용한 코드는 아래와 같다.
// configStore.js
import {configureStore} from "@reduxjs/toolkit";
import counter from "../modules/counters";
// 만든 리듀서를 통해 store를 생성.
const store = configureStore({reducer: counter});
// 생성한 리듀서를 export(내보낸다.)
export default store;
configureStore를 사용해서 한 번에 관리할 수 있다.
const store = configureStore({reducer: counter});
리듀서가 여러개라면 export한 함수를 reducer 부분에 더 추가하면된다.
아래처럼.
const store = configureStore({
reducer: {
counter: counter,
counter2: counter2
}
});
또는
const store = configureStore({
reducer: {
counter,
counter2
}
});
물론 import, export는 필수다.
Redux Module
툴킷을 적용하기 전의 코드는 아래와 같다.
// counter.js
// Action Value
const ADD_NUMBER = "ADD_NUMBER";
const DEL_NUMBER = "DEL_NUMBER";
// Action Creator
export const addNumber = (payload) => {
return {
type: ADD_NUMBER,
payload: payload,
};
};
export const delNumber = (payload) => {
return {
type: DEL_NUMBER,
payload: payload,
};
};
// Initial State
const initialState = {
number: 0,
};
// Reducer
const counter = (state = initialState, action) => {
switch (action.type) {
case ADD_NUMBER:
return {
number: state.number + action.payload,
};
case DEL_NUMBER:
return {
number: state.number - action.payload,
};
default:
return state;
}
};
// export default reducer
export default counter;
툴킷은 적용한 코드는 아래와 같다.
// counters.js
import {createSlice} from "@reduxjs/toolkit";
// Action Creator
// 비어있음
// Initial State
const initialState = {
number: 0,
};
// Reducer
const counter = createSlice({
name: "counter",
initialState,
reducers: {
addNumber: (state, action) => {
state.number = state.number + action.payload;
},
deleteNumber: (state, action) => {
state.number = state.number - action.payload;
},
},
});
// export default reducer
export const counterActions = counter.actions;
export default counter.reducer;
기존 코드에서의 Action Creator 부분이 Reducer에 들어갔다!
Action Value 부분도 필요없어졌다.
만약 initialState가 number말고도 addName 같은 데이터를 받는다면,
아래처럼 initialState에 다른 값을 넣고, 아래 리듀서 addNumber 부분에
state.addName = state.addName = action.payload.name; 을 넣는 것으로 데이터를 저장할 수 있다.
// counters.js
import {createSlice} from "@reduxjs/toolkit";
// Action Creator
// 비어있음
// Initial State
const initialState = {
number: 0,
addName : '',
};
// Reducer
const counter = createSlice({
name: "counter",
initialState,
reducers: {
addNumber: (state, action) => {
state.number = state.number + action.payload;
state.addName = state.addName = action.payload.name;
},
deleteNumber: (state, action) => {
state.number = state.number - action.payload;
},
},
});
// export default reducer
export const counterActions = counter.actions;
export default counter.reducer;
Redux Dispatch
아래는 툴킷 적용 전 코드다.
// src/App.js
import React, {useState} from "react";
import {useSelector, useDispatch} from "react-redux";
import {addNumber, delNumber} from "./redux/modules/counter";
const App = () => {
const [number, setNumber] = useState(0);
const globalNumber = useSelector((state) => state.counter.number);
const dispatch = useDispatch();
const onChangeHandler = (event) => {
setNumber(Number(event.target.value));
};
const onClickAddNumberHandler = () => {
dispatch(addNumber(number));
};
const onClickDelNumberHandler = () => {
dispatch(delNumber(number));
};
console.log(number);
return (
<div>
{globalNumber}
<input onChange={onChangeHandler} type="number" />
<button onClick={onClickAddNumberHandler}>더하기</button>
<button onClick={onClickDelNumberHandler}>빼기</button>
</div>
);
};
export default App;
아래는 툴킷 적용 후의 코드다.
// src/App.js
import React, {useState} from "react";
import {useSelector, useDispatch} from "react-redux";
import {counterActions} from "./redux/modules/counters";
const App = () => {
const [number, setNumber] = useState(0);
const globalNumber = useSelector((state) => state.number);
const globalName = useSelector((state) => state.addName);
const onChangeHandler = (event) => {
setNumber(Number(event.target.value));
};
const dispatch = useDispatch();
const onClickAddNumberHandler = () => {
dispatch(counterActions.addNumber({name: "kim", num: number}));
};
const onClickDelNumberHandler = () => {
dispatch(counterActions.deleteNumber(number));
};
return (
<div>
{globalNumber} {globalName}
<input onChange={onChangeHandler} type="number" />
<button onClick={onClickAddNumberHandler}>더하기</button>
<button onClick={onClickDelNumberHandler}>빼기</button>
</div>
);
};
export default App;
payload로 객체를 주는 것으로 name과 num을 저장시켰다.
확실히 리듀서 안에 다 때려넣으니 편한 것 같다.
리엑트로 만들던 사이드 프로젝트를 파이어베이스 9버전으로 리팩토링하고,
다시 그걸 redux를 적용한 것으로 리팩토링 했었는데,
이젠 툴킷을 적용한 redux로 리팩토링 해야겠다 ㅎㅎㅎㅎㅎㅎㅎㅎ ㅜㅜ