1. 라이브러리 설치
yarn add react-redux
yarn add @reduxjs/toolkit
2. Redux Store 설정
📁 redux / 📁 store / 📑 store.ts
타입스크립트로 만든 프로젝트라 RootState를 추가해주었다 RootState타입이 스토어의 상태를 나타내는 타입으로 정의된다.
import { configureStore } from "@reduxjs/toolkit";
import todoSlice from "../slices/todoSlice";
export const store = configureStore({
reducer: {
todos: todoSlice,
},
});
export type RootState = ReturnType<typeof store.getState>;
3.Slice 생성 및 액션 추가
📁 redux / 📁 slices / 📑 todoSlice.ts
todolist에 들어갈 내용은 id, content, isDone(완료여부)로 구성하였다. 따로 타입 파일을 만들어 인터페이스로 정의해주었다.
import { createSlice } from "@reduxjs/toolkit";
import { TodosState } from "../../types/TodoType";
const initialState: TodosState = {
todos: [],
};
const todoSlice = createSlice({
name: "todos",
initialState,
reducers: {
addTodo: (state, action) => {
state.todos = [...state.todos, action.payload];
},
deleteTodo: (state, action) => {
state.todos = state.todos.filter((todo) => todo.id !== action.payload);
},
toggleTodo: (state, action) => {
const todo = state.todos.find((todo) => todo.id === action.payload);
todo ? (todo.isDone = !todo.isDone) : null;
},
},
});
export default todoSlice.reducer;
export const { addTodo, deleteTodo, toggleTodo } = todoSlice.actions;
3-1. 타입 정의
📁 types / 📑 TodoType.ts
export interface Todo {
id: number;
content: string;
isDone: boolean;
}
export interface TodosState {
todos: Todo[];
}
4. Store 통합
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { Provider } from "react-redux";
import { store } from "./redux/store/store.ts";
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
5. 화면에 보여주기
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "./redux/store/store";
import { useState } from "react";
import { addTodo, deleteTodo, toggleTodo } from "./redux/slices/todoSlice";
const App: React.FC = () => {
const [content, setContent] = useState<string>("");
const todos = useSelector((state: RootState) => state.todos.todos);
const dispatch = useDispatch();
const handleAdd = (e: React.MouseEvent<HTMLFormElement, MouseEvent>) => {
e.preventDefault();
const newTodo = {
id: Date.now(),
content,
isDone: false,
};
dispatch(addTodo(newTodo));
setContent("");
};
return (
<>
<form onSubmit={handleAdd}>
<input
type="text"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<button type="submit">추가</button>
</form>
<ul>
{todos.map((todo) => {
return (
<li key={todo.id}>
<h2>{todo.content}</h2>
<button onClick={() => dispatch(toggleTodo(todo.id))}>
{todo.isDone ? "취소하기" : "완료하기"}
</button>
<button onClick={() => dispatch(deleteTodo(todo.id))}>
삭제
</button>
</li>
);
})}
</ul>
</>
);
};
export default App;
'Typescript' 카테고리의 다른 글
[타입스크립트] '{}' 형식에 '??' 속성이 없습니다. (0) | 2024.07.09 |
---|---|
[타입스크립트] 바인딩 요소 '?'에 암시적으로 'any' 형식이 있습니다. (0) | 2024.06.27 |
[타입스크립트] 기본타입 훑어보기 (0) | 2024.06.26 |