Adding Local Storage option in my ToDo List site

Viewed 200

I made my basic ToDo list site after learning react. I wanted to add a function of saving the items on reload. I am a beginner in react so I am facing difficulty in this. I tried the following code:

import React from "react";
import ToDoList from "./components/ToDoList";
import Navbar from './components/Navbar'
import '../src/App.css'

export default function TodoInput() {

  const saveLocalTasks = () => {
    let savedTasks = localStorage.getItem('tasks')
    console.log(savedTasks)

    if (savedTasks) {
      return JSON.parse(localStorage.getItem('tasks'))
    } else {
      return []
    }
  }

  const [task, setTask] = React.useState('')
  const [count, setCount] = React.useState(0)
  const [taskList, setTaskList] = React.useState([saveLocalTasks()])
  const [disable, setDisable] = React.useState(true)

  
  const [viewTaskList, setViewTaskList] = React.useState(true)
  
  const updateTaskList = () => {
    setTaskList([...taskList, {object: task, key: Date.now()}])
    setTask('')
    setViewTaskList(false)
    setCount(count + 1)
    setDisable(true)
  }
  
  const inputValue = e => {
      setTask(e.target.value)

      e.target.value === '' || task === '' || task.length === 0
      ?
      setDisable(true)
      :
      setDisable(false)
  }
  // console.log(task.length)

  React.useEffect(() => {
    localStorage.setItem('tasks', JSON.stringify(taskList.object))
  }, [taskList])

    return (
      <div>
          <Navbar />
          <header>
            <div className="todolist-border">
                <div className="todo-input-form">
                    <input
                    className = "inputText" 
                    placeholder="Add a Task" 
                    value={task} 
                    onChange = {inputValue}
                    />
                    <button disabled = {disable} onClick = {updateTaskList} className="todo-add-button">+</button>
                </div>
                {
                  viewTaskList || count === 0
                  ?
                  <div className="pendingTasks-div">
                      <img className = "pending-task-image" 
                      src= "https://dm0qx8t0i9gc9.cloudfront.net/watermarks/image/rDtN98Qoishumwih/task-pending-cartoon-business-vector-illustrations_zJCs81OO_SB_PM.jpg"
                      alt="pending-tasks" />
                      <p className="no-task-message">There are no pending tasks!! #Enjoy</p>
                  </div>
                  :
                  <ToDoList count = {count} setCount = {setCount} task = {task} taskList = {taskList} setTaskList = {setTaskList}/>
                }
            </div>
          </header>
      </div>
    )
}

But the following error is coming up: enter image description here

The following is the code for ToDoList component:

import React from "react";

export default function ToDoList(props) {

    const deleteTaskListItem = (key) => {
        const updatedList = props.taskList.filter((item) => {
            return (
                item.key !== key
            )
        })
        props.setTaskList(updatedList)
        props.setCount(props.count - 1)
    }
    

    return(
        <div>
            {props.taskList.map((item) => {
                return (
                <div key = {item.key} className="todolist-div">
                    <input type="checkbox" className="list-checkbox">
                    </input>
                    <p>{item.object}</p>
                    <button onClick={()=>deleteTaskListItem(item.key)} className="delete-button">X</button>
                </div>
                )
            })}
        </div>
    )
}

Kindly suggest a method to add this feature.

1 Answers

The above error happens when you try to JSON.parse undefined. Check this link. Here, I tried to do some changes in your code on CodeSandbox. There you can find some changes I have made.

  • Firstly, you shouldn't try to set data in this useState const [taskList, setTaskList] = React.useState([saveLocalTasks()]). You should set data in useEffect.
  • In the following code, you are trying to save taskList.object but taskList is an array. The below code will throw an error.
    React.useEffect(() => {
      localStorage.setItem('tasks', JSON.stringify(taskList.object))
    }, [taskList])
    
  • As you asked in your question, you want to try to save data when the user reloads the window. You can achieve this by using window.onbeforeunload event (line 48).

Hope the above will help you.

P.S: The codesandbox code I shared isn't fully functional. I have made just some changes that will help you to go ahead with your coding. Thank you.

Related