From 52e64dd36ff42cdea23e814e704d373cae51a96e Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:59:47 +0900 Subject: [PATCH 01/13] =?UTF-8?q?chore:=20ESLint=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20package.json=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eslint.config.js | 3 +++ package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/eslint.config.js b/eslint.config.js index 238d2e4..85f281a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -29,10 +29,13 @@ export default [ ...react.configs['jsx-runtime'].rules, ...reactHooks.configs.recommended.rules, 'react/jsx-no-target-blank': 'off', + "no-unused-vars" : "off", 'react-refresh/only-export-components': [ 'warn', { allowConstantExport: true }, + ], + 'react/no-unknown-property': ['error', { ignore: ['css'] }], }, }, ] diff --git a/package.json b/package.json index 9f1bcb2..ef82f8c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@emotion/react": "^11.13.3", "react": "^18.3.1", "react-dom": "^18.3.1" }, From 71392383ba9e77c1c01ca009607df214682b08f1 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Tue, 3 Sep 2024 01:24:49 +0900 Subject: [PATCH 02/13] =?UTF-8?q?feat=20localStorage=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/App.jsx b/src/App.jsx index 852a9fe..ffac339 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,44 @@ +/** @jsxImportSource @emotion/react */ +import { useState, useEffect } from 'react'; +import { css } from '@emotion/react'; +import TodoInput from './components/TodoInput'; +import TodoList from './components/TodoList'; + +const containerStyle = css` + max-width: 400px; + margin: 100px auto; + padding: 20px; + background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%); + border-radius: 20px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); +`; + +const titleStyle = css` + font-size: 24px; + text-align: center; + margin-bottom: 20px; +`; + function App() { - return
React Todo
; + const [todos, setTodos] = useState(() => { + // 로컬 스토리지에서 저장된 todos 가져오기 + const savedTodos = localStorage.getItem('todos'); + return savedTodos ? JSON.parse(savedTodos) : []; + }); + + useEffect(() => { + // todos 상태가 변경될 때마다 로컬 스토리지에 저장 + localStorage.setItem('todos', JSON.stringify(todos)); + }, [todos]); + + // 컴포넌트 렌더링 + return ( +
+

투두리스트

+ + +
+ ); } export default App; From 5ebbb9427cb7353c6db896562d5ac5a3d1eb76ab Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Tue, 3 Sep 2024 01:29:23 +0900 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20=ED=95=A0=EC=9D=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/App.jsx b/src/App.jsx index ffac339..97efb23 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -31,6 +31,22 @@ function App() { localStorage.setItem('todos', JSON.stringify(todos)); }, [todos]); + // 새 할 일을 추가하는 함수 + const addTodo = (text) => { + setTodos(todos.concat({ text, completed: false })); + }; + + // 특정 인덱스의 할 일을 삭제하는 함수 + const deleteTodo = (index) => { + const newTodos = []; + for (let i = 0; i < todos.length; i++) { + if (i !== index) { + newTodos.push(todos[i]); // 삭제할 인덱스가 아닌 항목만 추가 + } + } + setTodos(newTodos); + }; + // 컴포넌트 렌더링 return (
@@ -41,4 +57,4 @@ function App() { ); } -export default App; +export default App; \ No newline at end of file From 01078dc34240140e996bb4f60a10024b328ebbba Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Tue, 3 Sep 2024 01:31:16 +0900 Subject: [PATCH 04/13] =?UTF-8?q?feat:=20=ED=95=A0=EC=9D=BC=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=83=81=ED=83=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/App.jsx b/src/App.jsx index 97efb23..a5a4005 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -46,6 +46,12 @@ function App() { } setTodos(newTodos); }; + // 특정 인덱스의 할 일의 완료 상태를 토글하는 함수 + const toggleTodo = (index) => { + setTodos(todos.map((todo, i) => + i === index ? { ...todo, completed: !todo.completed } : todo + )); + }; // 컴포넌트 렌더링 return ( From c3eabb34fed8cdafd798caf2e604824ad8692695 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:22:32 +0900 Subject: [PATCH 05/13] =?UTF-8?q?feat:=20=20=ED=95=A0=20=EC=9D=BC=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EA=B3=BC=20=EC=B6=94=EA=B0=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoInput.jsx | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/components/TodoInput.jsx diff --git a/src/components/TodoInput.jsx b/src/components/TodoInput.jsx new file mode 100644 index 0000000..6714f5f --- /dev/null +++ b/src/components/TodoInput.jsx @@ -0,0 +1,57 @@ +//** @jsxImportSource @emotion/react */ +import { useState } from 'react'; +import { css } from '@emotion/react'; + +const inputContainerStyle = css` + margin-bottom: 20px; + display: flex; + justify-content: center; + align-items: center; +`; + +const inputStyle = css` + padding: 10px; + width: 200px; + margin-right: 10px; + border: none; + border-radius: 5px; + outline: none; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +`; + +const buttonStyle = css` + padding: 10px; + cursor: pointer; + background-color: #ff7f7f; + border: none; + border-radius: 5px; + color: white; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); +`; + +function TodoInput({ addTodo }) { + const [input, setInput] = useState(''); // 입력 값을 관리하기 위한 상태 선언 + + // 폼 제출 시 호출되는 함수 + const handleSubmit = (e) => { + e.preventDefault(); // 기본 폼 제출 동작을 막음 + if (!input.trim()) return; // 입력 값이 공백일 경우 아무 작업도 하지 않음 + addTodo(input); + setInput(''); + }; + + return ( +
+ setInput(e.target.value)} // 입력 값이 변경될 때마다 상태 업데이트 + placeholder="할일을 입력하세요" + /> + {/* 할 일을 추가하는 버튼 */} +
+ ); +} + +export default TodoInput; \ No newline at end of file From ebbd0d4956600c1a2e160ea3149f986f8413e7a1 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:29:22 +0900 Subject: [PATCH 06/13] =?UTF-8?q?=20feat:=20=ED=95=A0=EC=9D=BC=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EA=B4=80=EB=A6=AC=20=EB=B0=8F=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoItem.jsx | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/components/TodoItem.jsx diff --git a/src/components/TodoItem.jsx b/src/components/TodoItem.jsx new file mode 100644 index 0000000..8312979 --- /dev/null +++ b/src/components/TodoItem.jsx @@ -0,0 +1,38 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; + +const itemStyle = css` + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.5); + cursor: pointer; + color: #fff; +`; + +const completedStyle = css` + text-decoration: line-through; + color: #aaa; +`; + +const buttonStyle = css` + background: none; + border: none; + color: #fff; + cursor: pointer; +`; + +function TodoItem({ todo, index, deleteTodo, toggleTodo }) { + return ( + // 할 일이 완료되었는지 여부에 따라 itemStyle 또는 completedStyle을 적용 + //할 일 텍스트, 클릭 시 완료 상태를 토글 + //삭제 버튼, 클릭 시 할 일 삭제 +
+ toggleTodo(index)}>{todo.text} + +
+ ); +} + +export default TodoItem; From c0bb087cba2999f0a4508af6d2f58e60b5b83685 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Tue, 3 Sep 2024 09:39:20 +0900 Subject: [PATCH 07/13] =?UTF-8?q?=20feat:=20=ED=95=A0=20=EC=9D=BC=EC=9D=98?= =?UTF-8?q?=20=EC=A0=84=EC=B2=B4=EB=AA=A9=EB=A1=9D=20=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20=ED=91=9C=EC=8B=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoList.jsx | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/components/TodoList.jsx diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx new file mode 100644 index 0000000..579679b --- /dev/null +++ b/src/components/TodoList.jsx @@ -0,0 +1,45 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; +import TodoItem from './TodoItem.jsx'; + +const listContainerStyle = css` + width: 300px; + max-width: 100%; + margin: 0 auto; +`; + +function TodoList({ todos, deleteTodo, toggleTodo }) { + // 완료되지 않은 할 일만 필터링 + const pendingTodos = todos.filter((todo) => !todo.completed); + // 완료된 할 일만 필터링 + const completedTodos = todos.filter((todo) => todo.completed); + + return ( +
+

{pendingTodos.length}개의 할일이 남아있어요

+ {/* 남은 할 일 목록을 렌더링 */} + {pendingTodos.map((todo, index) => ( + + ))} +

{completedTodos.length}개의 할일을 완료했어요

+ {/* 완료한 할 일 목록을 렌더링 */} + {completedTodos.map((todo, index) => ( + + ))} +
+ ); +} + +export default TodoList; From 38ea3024f51b6c07e1a9a93d7676ebce8188ef40 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:48:32 +0900 Subject: [PATCH 08/13] =?UTF-8?q?feat:=20TodoHeader=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoHeader.jsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/components/TodoHeader.jsx diff --git a/src/components/TodoHeader.jsx b/src/components/TodoHeader.jsx new file mode 100644 index 0000000..8077879 --- /dev/null +++ b/src/components/TodoHeader.jsx @@ -0,0 +1,14 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; + +const titleStyle = css` + font-size: 24px; + text-align: center; + margin-bottom: 20px; +`; + +function TodoHeader() { + return

📚 TodoList

; +} + +export default TodoHeader; From 78e6fb6fe730be0306e29aea54257bd430517f40 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:49:33 +0900 Subject: [PATCH 09/13] =?UTF-8?q?feat:=20TodoButton=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoButton.jsx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/components/TodoButton.jsx diff --git a/src/components/TodoButton.jsx b/src/components/TodoButton.jsx new file mode 100644 index 0000000..15e4bab --- /dev/null +++ b/src/components/TodoButton.jsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; + +const buttonStyle = css` + padding: 10px; + cursor: pointer; + background-color: #ff7f7f; + border: none; + border-radius: 5px; + color: white; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + margin-left: 8px; +`; + +function TodoButton({ onClick, children }) { + return ( + + ); +} + +export default TodoButton; From b9eb4fa878959d4d527838b011c406fc36acf44c Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:50:31 +0900 Subject: [PATCH 10/13] =?UTF-8?q?feat:=20TodoListSection=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoListSection.jsx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/components/TodoListSection.jsx diff --git a/src/components/TodoListSection.jsx b/src/components/TodoListSection.jsx new file mode 100644 index 0000000..4d1bdc9 --- /dev/null +++ b/src/components/TodoListSection.jsx @@ -0,0 +1,26 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; +import TodoItem from './TodoItem'; + +const sectionStyle = css` + margin-bottom: 20px; +`; + +function TodoListSection({ title, todos, deleteTodo, toggleTodo }) { + return ( +
+

{title} ({todos.length})

+ {todos.map((todo, index) => ( + + ))} +
+ ); +} + +export default TodoListSection; From 2d78e6e6748f4c4d8f811c92beaed87f32331966 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:57:22 +0900 Subject: [PATCH 11/13] =?UTF-8?q?refactor:=20TodoListSection=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A5=BC=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=ED=95=A0=20=EC=9D=BC=20=EC=84=B9=EC=85=98?= =?UTF-8?q?=EC=9D=84=20=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoList.jsx | 47 +++++++++++++++---------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx index 579679b..6be7e7d 100644 --- a/src/components/TodoList.jsx +++ b/src/components/TodoList.jsx @@ -1,6 +1,7 @@ /** @jsxImportSource @emotion/react */ import { css } from '@emotion/react'; -import TodoItem from './TodoItem.jsx'; +import TodoListSection from './TodoListSection'; + const listContainerStyle = css` width: 300px; @@ -9,37 +10,27 @@ const listContainerStyle = css` `; function TodoList({ todos, deleteTodo, toggleTodo }) { - // 완료되지 않은 할 일만 필터링 - const pendingTodos = todos.filter((todo) => !todo.completed); - // 완료된 할 일만 필터링 - const completedTodos = todos.filter((todo) => todo.completed); + const pendingTodos = todos.filter((todo) => !todo.completed); // 완료되지 않은 할 일만 필터링 + const completedTodos = todos.filter((todo) => todo.completed); // 완료된 할 일만 필터링 return (
-

{pendingTodos.length}개의 할일이 남아있어요

- {/* 남은 할 일 목록을 렌더링 */} - {pendingTodos.map((todo, index) => ( - - ))} -

{completedTodos.length}개의 할일을 완료했어요

- {/* 완료한 할 일 목록을 렌더링 */} - {completedTodos.map((todo, index) => ( - - ))} + {/* TO DO 섹션 */} + + {/* DONE 섹션 */} +
); } -export default TodoList; +export default TodoList; From 60ada818ff0d8cec777c4221f437695395792719 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Wed, 4 Sep 2024 14:19:49 +0900 Subject: [PATCH 12/13] =?UTF-8?q?refactor:=20TodoItem=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EC=97=90=EC=84=9C=20TodoButton=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoItem.jsx | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/TodoItem.jsx b/src/components/TodoItem.jsx index 8312979..ee00191 100644 --- a/src/components/TodoItem.jsx +++ b/src/components/TodoItem.jsx @@ -1,6 +1,8 @@ /** @jsxImportSource @emotion/react */ import { css } from '@emotion/react'; +import TodoButton from './TodoButton'; +// Todo 항목의 기본 스타일 정의 const itemStyle = css` display: flex; align-items: center; @@ -11,28 +13,26 @@ const itemStyle = css` color: #fff; `; +// 완료된 Todo 항목 스타일 정의 const completedStyle = css` - text-decoration: line-through; + text-decoration: line-through; // 완료된 항목을 취소선으로 표시 color: #aaa; `; -const buttonStyle = css` - background: none; - border: none; - color: #fff; - cursor: pointer; -`; - +// 개별 Todo 항목을 나타내는 컴포넌트 function TodoItem({ todo, index, deleteTodo, toggleTodo }) { return ( - // 할 일이 완료되었는지 여부에 따라 itemStyle 또는 completedStyle을 적용 - //할 일 텍스트, 클릭 시 완료 상태를 토글 - //삭제 버튼, 클릭 시 할 일 삭제 -
- toggleTodo(index)}>{todo.text} - -
+
+ {/* 할 일 텍스트 표시 */} + {todo.text} +
+ {/* 할 일 완료 상태를 토글하는 버튼 */} + toggleTodo(index)}>✔️ + {/* 할 일을 삭제하는 버튼 */} + deleteTodo(index)}>🗑️ +
+
); } -export default TodoItem; +export default TodoItem; \ No newline at end of file From b4b5049361c0bd892f20e7f999089b0845fecf93 Mon Sep 17 00:00:00 2001 From: jissssu <113964353+jissssu@users.noreply.github.com> Date: Wed, 4 Sep 2024 14:22:41 +0900 Subject: [PATCH 13/13] =?UTF-8?q?feat:=20App=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index a5a4005..4cd76c4 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -3,6 +3,8 @@ import { useState, useEffect } from 'react'; import { css } from '@emotion/react'; import TodoInput from './components/TodoInput'; import TodoList from './components/TodoList'; +import TodoHeader from './components/TodoHeader'; + const containerStyle = css` max-width: 400px; @@ -13,17 +15,12 @@ const containerStyle = css` box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); `; -const titleStyle = css` - font-size: 24px; - text-align: center; - margin-bottom: 20px; -`; function App() { const [todos, setTodos] = useState(() => { // 로컬 스토리지에서 저장된 todos 가져오기 const savedTodos = localStorage.getItem('todos'); - return savedTodos ? JSON.parse(savedTodos) : []; + return savedTodos ? JSON.parse(savedTodos) : []; // 저장된 값이 있으면 파싱하여 사용, 없으면 빈 배열 }); useEffect(() => { @@ -31,36 +28,30 @@ function App() { localStorage.setItem('todos', JSON.stringify(todos)); }, [todos]); - // 새 할 일을 추가하는 함수 - const addTodo = (text) => { - setTodos(todos.concat({ text, completed: false })); + // 새 할 일을 추가하는 함수 + const addTodo = (text) => { + setTodos(todos.concat({ text, completed: false })); // 새로운 할 일을 기존 할 일 리스트에 추가 }; // 특정 인덱스의 할 일을 삭제하는 함수 const deleteTodo = (index) => { - const newTodos = []; - for (let i = 0; i < todos.length; i++) { - if (i !== index) { - newTodos.push(todos[i]); // 삭제할 인덱스가 아닌 항목만 추가 - } - } - setTodos(newTodos); + setTodos(todos.filter((_, i) => i !== index)); // 해당 인덱스의 할 일을 제외하고 새로운 리스트 생성 }; + // 특정 인덱스의 할 일의 완료 상태를 토글하는 함수 const toggleTodo = (index) => { - setTodos(todos.map((todo, i) => + setTodos(todos.map((todo, i) => i === index ? { ...todo, completed: !todo.completed } : todo - )); + )); // 할 일의 완료 상태를 반전시킴 }; - // 컴포넌트 렌더링 return (
-

투두리스트

- - + + +
); } -export default App; \ No newline at end of file +export default App;