diff --git a/package.json b/package.json
index a1dbacd..7784d15 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,8 @@
"react-redux": "8.1.1",
"react-scripts": "5.0.1",
"styled-components": "6.0.5",
- "web-vitals": "^2.1.0"
+ "web-vitals": "^2.1.0",
+ "zustand": "4.3.9"
},
"scripts": {
"start": "react-scripts start",
diff --git a/src/App.js b/src/App.js
index 1eade34..557b2bf 100644
--- a/src/App.js
+++ b/src/App.js
@@ -6,7 +6,7 @@ import TodoList from "./components/TodoList";
const App = () => {
return (
- 리덕스로 만드는 투두리스트
+ zustand로 만드는 투두리스트
diff --git a/src/components/TodoInput.jsx b/src/components/TodoInput.jsx
index 8378dc3..e52146f 100644
--- a/src/components/TodoInput.jsx
+++ b/src/components/TodoInput.jsx
@@ -1,23 +1,20 @@
import React, { useState } from "react";
import { styled } from "styled-components";
-import { useDispatch } from "react-redux";
-import { addTodo } from "../redux/modules/todoSlice";
+import { useTodoStore } from "../store/useTodoStore";
const TodoInput = () => {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
- const dispatch = useDispatch();
+ const { addTodo } = useTodoStore((state) => state);
const handleClick = () => {
- dispatch(
- addTodo({
- id: Date.now(),
- title,
- content,
- isDone: false,
- })
- );
+ addTodo({
+ id: Date.now(),
+ title,
+ content,
+ isDone: false,
+ });
};
return (
diff --git a/src/components/TodoItem.jsx b/src/components/TodoItem.jsx
index 039b270..5cebd1a 100644
--- a/src/components/TodoItem.jsx
+++ b/src/components/TodoItem.jsx
@@ -1,20 +1,19 @@
import React from "react";
import { styled } from "styled-components";
-import { useDispatch } from "react-redux";
-import { deleteTodo, updateTodo } from "../redux/modules/todoSlice";
+import { useTodoStore } from "../store/useTodoStore";
const TodoItem = (props) => {
const { todo } = props;
const { id, title, content, isDone } = todo;
- const dispatch = useDispatch();
+ const { deleteTodo, updateTodo } = useTodoStore((state) => state);
const deleteTodoItem = (id) => {
- dispatch(deleteTodo(id));
+ deleteTodo(id);
};
const updateTodoItem = (id) => {
- dispatch(updateTodo(id));
+ updateTodo(id);
};
return (
diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx
index a57765a..548a068 100644
--- a/src/components/TodoList.jsx
+++ b/src/components/TodoList.jsx
@@ -1,10 +1,10 @@
import React from "react";
import { styled } from "styled-components";
import TodoItem from "./TodoItem";
-import { useSelector } from "react-redux";
+import { useTodoStore } from "../store/useTodoStore";
const TodoList = () => {
- const { todos } = useSelector((state) => state.todoReducer);
+ const todos = useTodoStore((state) => state.todos);
return (
diff --git a/src/index.js b/src/index.js
index a2d4630..fc0b2a1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,15 +1,11 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
-import { Provider } from "react-redux";
-import { store } from "./redux/config/configStore";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
-
-
-
-
-
+
+
+
);
diff --git a/src/redux/config/configStore.js b/src/redux/config/configStore.js
deleted file mode 100644
index 42609cf..0000000
--- a/src/redux/config/configStore.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { configureStore } from "@reduxjs/toolkit";
-
-import todoReducer from "../modules/todoSlice";
-
-export const store = configureStore({
- reducer: {
- todoReducer,
- },
-});
diff --git a/src/redux/modules/todoSlice.js b/src/redux/modules/todoSlice.js
deleted file mode 100644
index 3ee6d00..0000000
--- a/src/redux/modules/todoSlice.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { createSlice } from "@reduxjs/toolkit";
-
-const name = "todos";
-
-const initialState = {
- todos: [],
-};
-
-export const counterSlice = createSlice({
- name,
- initialState,
- reducers: {
- addTodo: (state, action) => {
- state.todos.push(action.payload);
- },
- updateTodo: (state, action) => {
- const todo = state.todos.find((todo) => todo.id === action.payload);
- todo.isDone = !todo.isDone;
- },
- deleteTodo: (state, action) => {
- state.todos = state.todos.filter((todo) => todo.id !== action.payload);
- },
- },
- extraReducers: {},
-});
-
-// Action creators are generated for each case reducer function
-export const { addTodo, deleteTodo, updateTodo } = counterSlice.actions;
-
-export default counterSlice.reducer;
diff --git a/src/shared/Layout.jsx b/src/shared/Layout.jsx
index e991db7..7d28478 100644
--- a/src/shared/Layout.jsx
+++ b/src/shared/Layout.jsx
@@ -1,8 +1,13 @@
-import React from "react";
+import React, { useEffect } from "react";
import GlobalStyle from "../styles/GlobalStyle";
import { styled } from "styled-components";
+import { fetchTodos } from "../store/useTodoStore";
const Layout = ({ children }) => {
+ useEffect(() => {
+ fetchTodos();
+ }, []);
+
return (
diff --git a/src/store/useTodoStore.js b/src/store/useTodoStore.js
new file mode 100644
index 0000000..fde237f
--- /dev/null
+++ b/src/store/useTodoStore.js
@@ -0,0 +1,28 @@
+import { create } from "zustand";
+
+export const useTodoStore = create((set) => ({
+ todos: [],
+ setTodos: (todos) => set({ todos }),
+ addTodo: (newTodo) => set((state) => ({ todos: [...state.todos, newTodo] })),
+ updateTodo: (id) =>
+ set((state) => ({
+ todos: state.todos.map((todo) => {
+ if (todo.id === id) {
+ return { ...todo, isDone: !todo.isDone };
+ }
+ return todo;
+ }),
+ })),
+ deleteTodo: (id) =>
+ set((state) => ({ todos: state.todos.filter((todo) => todo.id !== id) })),
+}));
+
+export const fetchTodos = async () => {
+ const response = await fetch(
+ "https://jsonplaceholder.typicode.com/todos?_limit=3"
+ );
+ const todos = await response.json();
+ useTodoStore
+ .getState()
+ .setTodos(todos.map((todo) => ({ ...todo, isDone: false })));
+};
diff --git a/yarn.lock b/yarn.lock
index 65ff377..ce9e57d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9083,7 +9083,7 @@ url-parse@^1.5.3:
querystringify "^2.1.1"
requires-port "^1.0.0"
-use-sync-external-store@^1.0.0:
+use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
@@ -9649,3 +9649,10 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
+zustand@4.3.9:
+ version "4.3.9"
+ resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad"
+ integrity sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw==
+ dependencies:
+ use-sync-external-store "1.2.0"