Search code examples
javascriptarraysobjectlocal-storage

making a basic todo list. on refresh when accessing local storage to keep todo list I get {"TODO_ITEM:1":"wash dishes"} instead of wash dishes


I've made a very basic, bare bones todo list. When I add to the list through the input (wash dishes) it comes out as wash dishes. but on refresh when accessing the object in the array from local storage I get back {"TODO_ITEM:1":"wash dishes"}. My main question is where did I mess up and how do I go about fixing it. I'm assuming its a mess up in how I'm accessing the data. everything I look up and find on accessing the value of an object either doesn't work, says its not a function or comes back as [object object]. this is probably my fifth project in coding as a first timer, any and all advice helps!

//Select everything
const list = document.querySelector('#todo-list');
const form = document.querySelector('#create-todo');
const input = document.querySelector('#new-todo');
let todoCount = 1;
let obj = {};
let todo = [];

// let data = localStorage.getItem('')
//Remove button to remove li
list.addEventListener('click', function(e) {
  if (e.target.tagName === 'LI') {
    e.target.classList.toggle('done');
  } else if (e.target.tagName === 'BUTTON') {
    e.target.parentElement.remove();
  }
})

// creating a new todo
form.addEventListener('submit', function(e) {
  //preventing refresh
  e.preventDefault();
  //adding array to local storage
  addToLocalStorage(todo)
  //creating and adding new li w/button to list
  createLi()

  console.log(localStorage)
})

//accessing local storage
function getFromLocalStorage() {
  const reference = localStorage.getItem('TODO_LIST')
  if (reference) {
    todo = JSON.parse(reference)
    renderTodo(todo)
  }
}

//new Li function
function createLi() {
  const newLi = document.createElement('li');
  const newBtn = document.createElement('button');

  newLi.innerText = input.value;
  list.append(newLi);

  newBtn.innerText = 'Remove';
  newLi.append(newBtn);
  input.value = '';
}

//add to local storage function
function addToLocalStorage(todo) {
  let obj = {}

  let key = 'TODO_ITEM:' + todoCount
  console.log(obj)
  todoCount++
  obj[key] = input.value
  todo.push(obj)
  localStorage.setItem('TODO_LIST', JSON.stringify(todo))
}

// keep todo list on refresh function
function renderTodo() {
  list.innerHTML = '';

  for (let i = 0; i < todo.length; i++) {
    console.log(todo[i])
    let indx = todo[i]
    const newLi = document.createElement('li');
    const newBtn = document.createElement('button');
    newLi.innerText = JSON.stringify(indx);
    list.append(newLi);
    console.log()
    newBtn.innerText = 'Remove';
    newLi.append(newBtn);
    console.log(indx)
  }
}

getFromLocalStorage();

Solution

  • Current Version

    The issue is that the todos are saved to localstorage as js objects with the format:

    // { key: value }
    {"TODO_ITEM:1": "Todo value"}
    

    So when you later extract it, you need to access the value of the object that holds the todo text:

    function getFromLocalStorage() {
      // this returns a list of todos in the above format
      const reference = localStorage.getItem('TODO_LIST');
    
      if (reference) {
        const todoItems = JSON.parse(reference);
    
        // loop over the todos array and get individual todos
        todoList = todoItems.map((item) => {
          // use Object.values to get the 'Todo value' from the object {"TODO_ITEM:1": "Todo value"}
          const todoValue = Object.values(item)[0];
          return todoValue;
        });
        todo = todoList;
        renderTodo(todo);
      }
    }
    

    Then later in your renderTodos function, don't stringify the value:

    // Remove this
    newLi.innerText = JSON.stringify(indx);
    
    // add this
    newLi.innerText = indx;
    

    You can learn more about Object.keys() here, and array.map() here.

    Better Version

    This process could have been a lot easier if you considered storing just a list of todo text as ['wash dishes', 'have some coffee'] etc. Adding the todo's as objects just complicates the logic given it is just a simple todo app.

    Therefore I suggest you implement something like this:

    addToLocalStorage function:

    function addToLocalStorage(todo) {
      todo.push(input.value);
      localStorage.setItem('TODO_LIST', JSON.stringify(todo));
    }
    

    getFromLocalStorage function:

    function getFromLocalStorage() {
      // this returns a stringified array of todos
      const reference = localStorage.getItem('TODO_LIST');
    
      if (reference) {
        todos = JSON.parse(reference);
        renderTodo();
      }
    }
    

    Hope it helps.