diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/src/App.jsx b/src/App.jsx index 0d2dbbe..44a25a2 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react' +import { useState, useEffect, useRef, useCallback, useMemo } from 'react' import Navbar from './components/Navbar' import { v4 as uuidv4 } from 'uuid'; @@ -11,20 +11,12 @@ function App() { // Load from localStorage on initial mount useEffect(() => { getFromLS() + // eslint-disable-next-line react-hooks/exhaustive-deps }, []) - // Save to localStorage when todos change (but skip first render) - useEffect(() => { - if (isFirstLoad.current) { - isFirstLoad.current = false - return - } - savetoLS() - }, [todos]) - - const handleInput = (e) => setTodo(e.target.value) + const handleInput = useCallback((e) => setTodo(e.target.value), []) - const handleSave = () => { + const handleSave = useCallback(() => { if (todo.trim() === "") { alert("Please enter a task") return @@ -34,43 +26,59 @@ function App() { text: todo, completed: false } - setTodos([...todos, newTodo]) + setTodos(prevTodos => [...prevTodos, newTodo]) setTodo("") - } + }, [todo]) - const savetoLS = () => { + const savetoLS = useCallback(() => { localStorage.setItem("todos", JSON.stringify(todos)) - } + }, [todos]) - const getFromLS = () => { + // Save to localStorage when todos change (but skip first render) + useEffect(() => { + if (isFirstLoad.current) { + isFirstLoad.current = false + return + } + savetoLS() + }, [savetoLS]) + + const getFromLS = useCallback(() => { const storedTodos = localStorage.getItem("todos") if (storedTodos) { setTodos(JSON.parse(storedTodos)) } - } + }, []) - const handleEdit = (id) => { - let t = todos.find((item) => item.id === id) - if (t) { - setTodo(t.text) - setTodos(todos.filter((item) => item.id !== id)) - } - } + const handleEdit = useCallback((id) => { + setTodos(prevTodos => { + const t = prevTodos.find((item) => item.id === id) + if (t) { + setTodo(t.text) + return prevTodos.filter((item) => item.id !== id) + } + return prevTodos + }) + }, []) - const handleDelete = (id) => { - setTodos(todos.filter((item) => item.id !== id)) - } + const handleDelete = useCallback((id) => { + setTodos(prevTodos => prevTodos.filter((item) => item.id !== id)) + }, []) - const toggleComplete = (id) => { - const updatedTodos = todos.map(todo => + const toggleComplete = useCallback((id) => { + setTodos(prevTodos => prevTodos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo - ) - setTodos(updatedTodos) - } + )) + }, []) + + const handleShowToggle = useCallback(() => { + setShowFinished(prev => !prev) + }, []) - const handleShowToggle = () => { - setShowFinished(!showFinished) - } + // Memoize filtered todos to avoid recalculating on every render + const filteredTodos = useMemo(() => { + return showFinished ? todos : todos.filter(item => !item.completed) + }, [todos, showFinished]) return ( <> @@ -111,8 +119,7 @@ function App() {

Your Tasks

- {todos.map((item) => ( - (showFinished || !item.completed) && + {filteredTodos.map((item) => (
{item.text} diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 08880d0..c986481 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,5 +1,3 @@ -import React from 'react' - const Navbar = () => { return (