Redux Toolkit은 createSlice
와 configureStore
함수를 제공하여 보일러 플레이트 코드를 줄일 수 있다. createSlice
함수는 Reducer 함수와 Action Creator 함수를 하나의 객체로 묶어주어 보다 간결한 코드를 작성할 수 있게 해주며, configureStore
함수는 Redux의 store를 생성하는데 사용된다.
createSlice
를 사용하여 Reducer 함수와 Action Creator 함수를 하나의 객체로 만들면, 해당 Reducer 함수의 동작을 변경할 때 모든 Action Creator 함수를 수정하지 않아도 된다. 또한, configureStore
함수를 사용하면 Redux store를 생성하면서 Redux DevTools Extension과 같은 미들웨어를 쉽게 추가할 수 있다.
//counterReducer.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface ICounterState {
value: number;
}
const counterInitialState: ICounterState = {
value: 0,
};
const counterSlice = createSlice({
name: "counter",
initialState: counterInitialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
//authReducer.ts
import { createSlice } from "@reduxjs/toolkit";
interface IAuthState {
isLoggedIn: boolean;
}
const authInitialState: IAuthState = {
isLoggedIn: false,
};
const authSlice = createSlice({
name: "auth",
initialState: authInitialState,
reducers: {
login: (state) => {
state.isLoggedIn = true;
},
logout: (state) => {
state.isLoggedIn = false;
},
},
});
export const { login, logout } = authSlice.actions;
export default authSlice.reducer;
counter
와 auth
두 개의 slice를 생성하였습니다. 각각 increment
, decrement
, incrementByAmount
와 login
, logout
Action Creator 함수를 가지고 있다.//store.ts
import { configureStore } from "@reduxjs/toolkit";
import authReducer from "./reducers/authReducer";
import counterReducer from "./reducers/counterReducer";
export const store = configureStore({
reducer: {
auth: authReducer,
counter: counterReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
configureStore
함수를 사용하여 Redux store를 생성하고 reducer를 등록한다.authReducer
와 counterReducer
를 등록하여 store에 저장하였다.//index.tsx
import Auth from "@/components/Auth";
import Counter from "@/components/Counter";
import { RootState } from "@/slices/store";
import { useSelector } from "react-redux";
export default function Home() {
const isAuthenticated = useSelector(
(state: RootState) => state.auth.isLoggedIn
);
const count = useSelector((state: RootState) => state.counter.value);
return (
<>
<div>
<h1>Redux Test</h1>
<Auth />
<Counter />
<h1>전역 상태 테스트</h1>
<h1>auth : {isAuthenticated ? "login" : "logout"}</h1>
<h1>count : {count}</h1>
</div>
</>
);
}
useSelector
훅을 이용하여 auth
와 counter
상태를 가져온다. 이제 Auth 컴포넌트와 Counter 컴포넌트에서도 마찬가지로 useSelector
를 사용하여 상태를 가져올 수 있다.//Auth.tsx
import { login, logout } from "@/slices/reducers/authReducer";
import { RootState } from "@/slices/store";
import { useDispatch, useSelector } from "react-redux";
export default function Auth() {
const isAuthenticated = useSelector(
(state: RootState) => state.auth.isLoggedIn
);
const dispatch = useDispatch();
const handleLoginToggle = () => {
if (isAuthenticated) {
dispatch(logout());
} else {
dispatch(login());
}
};
return (
<>
<h1>Auth.tsx</h1>
<h1>{isAuthenticated ? "Logged In" : "Not Logged In"}</h1>
<h1 onClick={handleLoginToggle}>
Log In Toggle
</h1>
</>
);
}
//Counter.tsx
import { decrement, increment } from "@/slices/reducers/counterReducer";
import { RootState } from "@/slices/store";
import { useDispatch, useSelector } from "react-redux";
export default function Counter() {
const count = useSelector((state: RootState) => state.counter.value);
const dispatch = useDispatch();
const handleIncrement = () => {
dispatch(increment());
};
const handleDecrement = () => {
dispatch(decrement());
};
return (
<>
<h1>Counter.tsx</h1>
<h1 onClick={handleIncrement}>
INCREMENT
</h1>
<h1>number : {count}</h1>
<h1 onClick={handleDecrement}>
DECREMENT
</h1>
</>
);
}
useDispatch
훅을 이용하여 Reucer에서 만든 action을 준다.