Redux에서 상태를 더욱 쉽게 관리하고 구조화하는 데 도움을 주는 패키지로 Redux를 사용할 때 자주 사용되는 패턴과 기능을 쉽게 구현할 수 있도록 도와준다.
name
을 가져야한다.initialState
)과 reducer
를 설정해야한다.payload
인 곳에 자동으로 저장한다.createSlice 에서 reducer를 정의할 때에는 개발자가 불변성을 고려하면서 작성하지 않아도, 내부적으로 immer 라이브러리를 사용해서 안전하게 불변성을 유지하면서 변화한 상태 객체를 반환시킨다. 즉, createSlice 안에서는 그냥 이전 상태값에 새로운 값을 대입하듯이 코드를 작성해도 괜찮다.
//store/index.js
import { configureStore, createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0, show : true },
reducers: {
increment: (state) => {
state.value++;
},
decrement: (state) => {
state.value--;
},
//action.payload값을 받아서 그만큼 이전값에 더한다.
increase: (state, action) => {
state.value += action.payload;
},
toggleCounter: (state) => {
state.show = !state.show;
},
},
});
//store/index.js
const store = configureStore({
//여러개의 리듀서 합치기
reducer: {
counter: counterSlice.reducer,
},
});
export const counterAction = counterSlice.actions
export default store;
//action을 사용하려는 컴포넌트
import { useSelector, useDispatch } from 'react-redux'
import { counterAction } from '../store/index'
function App(){
const dispatch = useDispatch();
const show = useSelector((state) => state.counter.show);
const value = useSelector((state) => state.counter.value);
const incrementHandler = () =>{
dispatch(counterAction.increment());
}
const decrementHandler = () =>{
dispatch(counterAction.decrement());
}
const increaseHandler = (n) =>{
//action.payload로 n 값이 전달된다.
dispatch(counterAction.increase(n));
}
const showHandler = () =>{
dispatch(counterAction.toggle());
}
}
redux-toolkit에서는 비동기 처리를 하기 위해 creatAsyncThunk를 사용하면 따로 미들웨어 설정을 할 필요 없다.
import {createSlice, createAsyncThunk} from "@reduxjs/toolkit";
import axios from "axios";
export const loadBucket = createAsyncThunk(
// action 이름
"load/Bucket",
// 처리할 비동기 함수
async () => {
const res = await axios.get("http://localhost:5008/bucket");
// action의 payload 리턴
return res.data;
}
);
const bucketSlice = createSlice({
name: "bucket",
initialState: {list: []},
reducers: {},
// 비동기 함수의 pending, fulfilled, rejected를 처리할 내용을 넣어준다.
extraReducers: {
[loadBucket.pending]: (state, action) => {
console.log('pending');
},
// 비동기 함수가 fulfilled 되었을 때, state를 변경
[loadBucket.fulfilled]: (state, action) => {
state.list = action.payload;
console.log('fulfilled');
},
[loadBucket.rejected]: (state, action) => {
console.log('rejected')
}
}
})
export default bucketSlice.reducer;
import {loadBucket} from "./store/bucketSlice";
import {useDispatch, useSelector} from "react-redux";
import {useEffect} from "react";
const App = () => {
const bucket_list = useSelector(state => state.bucket.list);
const dispatch = useDispatch();
useEffect(() => {
//createAsyncThunk 호출
dispatch(loadBucket());
}, [])
return (
<>
{bucket_list.map((item, index) => (
<div key={index}>
{item.text}
</div>
))}
</>
);
}
export default App;