
npm install @reduxjs/toolkit react-redux

| 기능 | 기존 Redux | Redux Toolkit |
|---|---|---|
| Action 관리 | 직접 생성 | createSlice()에서 자동 생성 |
| Reducer 관리 | combineReducers() | createSlice()에서 통합 |
| Store 생성 | createStore() | configureStore() |
| 미들웨어 추가 | applyMiddleware() 사용 | configureStore()에서 자동 포함 |
| 비동기 작업 | Redux-Thunk 사용 | createAsyncThunk() 제공 |
createSlice()로 Reducer 및 Action 생성Redux에서는 Action, Reducer, Action Creator를 각각 만들어야 했지만,
Redux Toolkit의 createSlice()를 사용하면 한 번에 정의할 수 있음
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: "counter",
initialState: 0,
reducers: {
increment: (state) => state + 1,
decrement: (state) => state - 1,
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
reducers 객체 안에서 직접 상태를 변경 가능 counterSlice.actions에서 자동으로 액션 생성자(increment, decrement)가 생성됨 counterSlice.reducer가 리듀서 함수 역할을 함 configureStore()로 Store 생성configureStore()를 사용하여 전역 상태 저장소 생성
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
}
});
combineReducers()를 사용할 필요 없이 자동으로 여러 Reducer를 통합 const store = configureStore ({
reducer : {
counter : counterSlice.reducer,
any : anySlice.reducer,
... ...
}
})
Provider로 React에 연결React와 Redux Store를 연결하는 방식은 동일
Provider로 감싸서 상태를 전역적으로 사용할 수 있도록 설정
import App, { store } from './App.jsx';
import { Provider } from 'react-redux';
createRoot(document.getElementById('root')).render(
<Provider store={store}>
<App />
</Provider>,
);
useSelector와 useDispatch 사용상태를 가져오고 변경하는 방식은 기존 Redux와 동일
✅ useSelector를 사용해 상태값 가져오기
import { useSelector } from 'react-redux';
function App() {
const counter = useSelector(state => state.counter);
return (
<>
<div>counter : {counter}</div>
<button>+</button>
<button>-</button>
</>
);
}
✅ useDispatch를 사용해 상태 변경하기
import { useDispatch } from 'react-redux';
function App() {
const dispatch = useDispatch();
return (
<>
<button onClick={() => dispatch(counterSlice.actions.increment())}>+</button>
<button onClick={() => dispatch(counterSlice.actions.decrement())}>-</button>
</>
);
}
createAsyncThunk()Redux Toolkit에서 비동기 API 호출 등을 처리하기 위해 createAsyncThunk()를 사용
import { createAsyncThunk } from '@reduxjs/toolkit';
export const slowIncrementThunk = createAsyncThunk(
'counter/slowIncrement', // 액션 타입
async (_, { dispatch }) => { // 비동기 함수 실행
setTimeout(() => {
dispatch(counterSlice.actions.increment()); // 1초 후 증가
}, 1000);
}
);
import { configureStore } from '@reduxjs/toolkit';
import counterReducer, { slowIncrementThunk } from './counterSlice';
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
import { useSelector, useDispatch } from 'react-redux';
import { slowIncrementThunk } from './counterSlice';
function App() {
const counter = useSelector(state => state.counter);
const dispatch = useDispatch();
return (
<>
<h2>Slow Counter</h2>
<div>Counter : {counter}</div>
<button onClick={() => dispatch(slowIncrementThunk())}>1초 후 증가</button>
<button onClick={() => dispatch(counterSlice.actions.decrement())}>-</button>
</>
);
}
onClick 이벤트 발생 시 비동기 액션(dispatch) 실행 setTimeout()이 1초 후 실행되면서 dispatch(counterSlice.actions.increment()) 실행 counter 상태가 1 증가