보일러플레이트 코드(액션, 리듀서, 스토어 설정 등)를 최소화하면서, 개발자가 더욱 직관적으로 상태 관리npm i @reduxjs/toolkit
npm i react-redux
▪️ 간편한 스토어 설정 (configureStore)
configureStore는 자동으로 설정을 처리합니다.▪️ createSlice로 액션과 리듀서를 한번에 정의
createSlice를 사용하면 액션과 리듀서를 한 번에 정의할 수 있어 코드량이 줄어들고 가독성이 좋아집니다.▪️ createAsyncThunk를 활용한 비동기 처리
createAsyncThunk를 제공하여 간편하게 비동기 액션을 생성할 수 있습니다.▪️ 미들웨어 및 개발자 도구 지원
▪️ 종합 정리 !!
[Redux] Action / Reducer => [RTK] createSlice( )
[Redux] Store => [RTK] configureStore( )
---
그대로 사용되는 부분 ..
<Provider store={ store }>
useSelector( )
useDispatch( )
둘 중 하나 사용하여도 무방하다 !
(1)
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state) => state + 1, // state를 직접 수정
decrement: (state) => state - 1,
reset: () => 0,
},
},
});
(2)
const counterSlice = createSlice( {
name : 'counter',
initialState : 0,
reducers : {
increment ( state, action ) { return state += 1 },
decrement ( state, action) { return state -= 1 }
}
} )
리듀서를 전달받아 전역 상태 저장소를 생성 후 리액트 앱의 최상단에서 <Provider store={store}>로 감싸주기
// 리듀서를 전달받아 전역 상태 저장소를 생성
export const store = configureStore( {
reducer: {
counter: counterSlice.reducer,
any : anySlice.reducer,
... ...
}
} )
__________________________________________________
// 📁 최상단 jsx 파일로 이동하여 ...
<Provider store={store}>
<App />
</Provider>
createSlice에서 정의해준 reducers 이름으로 사용
// useSelector( ) 사용하여 가져와주기
const counter = useSelector(state => state.counter)
const dispatch = useDispatch();
<button onClick={() => {
dispatch( counterSlice.actions.increment( )
}
)} + </button>
<button onClick={() => {
dispatch( counterSlice.actions.decrement( )
}
)} - </button>
RTK에서 제공하는 Thunk 생성 함수, Redux-Thunk처럼 비동기 처리 가능 !
import './App.css'
import { useDispatch, useSelector } from 'react-redux'
import { configureStore, createAsyncThunk, createSlice } from '@reduxjs/toolkit'
// Slice 생성
const counterSlice = createSlice( {
name : 'counter',
initialState : 0,
reducers : {
increment ( state, action ) { return state += 1 },
decrement ( state, action) { return state -= 1 }
}
} )
// Store 생성
export const store = configureStore( {
reducer: {
counter: counterSlice.reducer,
}
} )
// 📍 Thunk 생성 - 비동기 함수
const slowIncrementThunk = createAsyncThunk(
// 변경할 리듀서 name / 액션 타입명 정해주기
'counter/slowIncrement',
// (value, {dispatch}) 고정 값으로 암기
(value, {dispatch}) => {
setTimeout(() => {
dispatch(counterSlice.actions.increment())
}, 1000);
}
)
function App() {
const counter = useSelector(state => state.counter)
const dispatch = useDispatch()
return (
<>
<div> Count : {counter} </div>
// ➕ 버튼만 Thunk 설정 !! - 1초 뒤 값 올리기
<button onClick={()=> dispatch(slowIncrementThunk())}>+</button>
<button onClick={()=> dispatch(counterSlice.actions.decrement())}>-</button>
</>
)
}
export default App
✔️ 코드 간결화 - 기존 Redux보다 코드 양이 줄어듦
✔️ 가독성 증가 - 액션, 리듀서, 스토어 설정이 직관적
✔️ 비동기 처리 간편화 - createAsyncThunk를 통해 쉽게 처리