오래간만에 Redux Toolkit으로 Todo List를 만드는데 다른 상태관리를 사용하다 보니 머릿속에 남지 않아서 이렇게 메모를 남긴다.
// store.ts
import { configureStore } from '@reduxjs/toolkit';
import todoSlice from '../modules/todoSlice';
const store = configureStore({
reducer: { todoSlice },
});
// store의 타입 '미리' 지정하여 export
export type RootState = ReturnType<typeof store.getState>;
//RootState의 타입을 지정해주는 이유는
//state의 reducer들의 타입을 제네릭형태로 지정해주어
//useSelector에서 특정 reducer를 return 해서 가져다 사용할 때 타입 추론이 가능해진다.
export type AppDispatch = typeof store.dispatch;
export default store;
store에서 타입 지정대상 RootState : reducer 만든 곳(=store)에서 useSelector의 ReturnType 을 지정하자AppDispatch : useDispatch의 타입을 지정하자// todoSlice.ts
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
// PayloadAction = action.payload 필드의 타입을 지정할 수 있게 해주는 제네릭이다.
interface Todo {
text: string;
id: number;
}
const initialState: Todo[] = [];
const todoSlice = createSlice({
name: 'todo',
initialState,
reducers: {
addTodo: (state, { payload }: PayloadAction<string>) => {
const id = Date.now();
state.push({ text: payload, id });
},
removeTodo: (state, { payload }: PayloadAction<number>) => {
return state.filter((todo) => todo.id !== payload);
},
},
});
export const { addTodo, removeTodo } = todoSlice.actions;
export default todoSlice.reducer;
initialState , action (payload) 예시가 있어야 이해력이 UPUP
import { useSelector } from 'react-redux';
import TodoCard from './TodoCard';
import useTodoSlice from '../hooks/useTodoSlice';
import { RootState } from '../store/config/store';
//import { RootState } from '@reduxjs/toolkit/query'; <- 이거 아니다...
const Sample = () => {
const todoSlice = useSelector((state: RootState) => state.todoSlice);
// store.ts에서 export한 RootState를 사용해야 reducers들을 추론해줌
const dispatch = useDispatch<AppDispatch>()
// useDispatch는 useState의 setState의 타입과 비슷하지 아니한가??
const { completeTodo } = useTodoSlice({});
return (
<div onClick={completeTodo}>
{todoSlice?.map((todo) => (
<TodoCard key={todo.id} text={todo.text} id={todo.id} />
))}
</div>
);
};
export default Sample;