diff --git a/package.json b/package.json
index a1dbacd..4a574f0 100644
--- a/package.json
+++ b/package.json
@@ -7,12 +7,14 @@
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.2.1",
+ "jotai": "2.2.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"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..94d80f4 100644
--- a/src/App.js
+++ b/src/App.js
@@ -6,7 +6,7 @@ import TodoList from "./components/TodoList";
const App = () => {
return (
- 리덕스로 만드는 투두리스트
+ jotai로 만드는 투두리스트
diff --git a/src/components/TodoInput.jsx b/src/components/TodoInput.jsx
index 8378dc3..f616ab0 100644
--- a/src/components/TodoInput.jsx
+++ b/src/components/TodoInput.jsx
@@ -1,23 +1,18 @@
import React, { useState } from "react";
import { styled } from "styled-components";
-import { useDispatch } from "react-redux";
-import { addTodo } from "../redux/modules/todoSlice";
+import { todosAtom } from "../store/atom";
+import { useAtom } from "jotai";
const TodoInput = () => {
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
- const dispatch = useDispatch();
+ const [_, setTodos] = useAtom(todosAtom);
const handleClick = () => {
- dispatch(
- addTodo({
- id: Date.now(),
- title,
- content,
- isDone: false,
- })
- );
+ setTodos((prev) => {
+ return [...prev, { id: Date.now(), title, content, isDone: false }];
+ });
};
return (
diff --git a/src/components/TodoItem.jsx b/src/components/TodoItem.jsx
index 039b270..da1a321 100644
--- a/src/components/TodoItem.jsx
+++ b/src/components/TodoItem.jsx
@@ -1,20 +1,29 @@
import React from "react";
import { styled } from "styled-components";
-import { useDispatch } from "react-redux";
-import { deleteTodo, updateTodo } from "../redux/modules/todoSlice";
+import { todosAtom } from "../store/atom";
+import { useAtom } from "jotai";
const TodoItem = (props) => {
const { todo } = props;
const { id, title, content, isDone } = todo;
-
- const dispatch = useDispatch();
+ const [_, setTodos] = useAtom(todosAtom);
const deleteTodoItem = (id) => {
- dispatch(deleteTodo(id));
+ setTodos((prev) => {
+ return prev.filter((todo) => todo.id !== id);
+ });
};
const updateTodoItem = (id) => {
- dispatch(updateTodo(id));
+ setTodos((prev) => {
+ return prev.map((todo) => {
+ if (todo.id === id) {
+ return { ...todo, isDone: !todo.isDone };
+ } else {
+ return todo;
+ }
+ });
+ });
};
return (
diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx
index a57765a..beb3d71 100644
--- a/src/components/TodoList.jsx
+++ b/src/components/TodoList.jsx
@@ -1,10 +1,11 @@
import React from "react";
import { styled } from "styled-components";
import TodoItem from "./TodoItem";
-import { useSelector } from "react-redux";
+import { useAtom } from "jotai";
+import { todosAtom } from "../store/atom";
const TodoList = () => {
- const { todos } = useSelector((state) => state.todoReducer);
+ const [todos] = useAtom(todosAtom);
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/store/atom.js b/src/store/atom.js
new file mode 100644
index 0000000..f060f9e
--- /dev/null
+++ b/src/store/atom.js
@@ -0,0 +1,3 @@
+import { atom } from "jotai";
+
+export const todosAtom = atom([]);
diff --git a/yarn.lock b/yarn.lock
index 65ff377..8a86bae 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6110,6 +6110,11 @@ jiti@^1.18.2:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1"
integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==
+jotai@2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.2.2.tgz#1e181789dcc01ced8240b18b95d9fa10169f9366"
+ integrity sha512-Cn8hnBg1sc5ppFwEgVGTfMR5WSM0hbAasd/bdAwIwTaum0j3OUPqBSC4tyk3jtB95vicML+RRWgKFOn6gtfN0A==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -9083,7 +9088,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 +9654,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"