1

I created to do list using react, but I want it to be local storage - so when the user refresh the page it still saved the items and will present them. I read I need to use localStorage but I'm not sure where and how, attach the app.js and TodoItem component

class App extends Component {
  state = {
    items: [],
    id: uuidv4(),
    item: "",
    editItem: false
  };
  handleChange = e => {
    ...
  };
  handleSubmit = e => {
    e.preventDefault();
    const newItem = {
      id: this.state.id,
      title: this.state.item
    };
    const updatedItems = [...this.state.items, newItem];

    this.setState({
      items: updatedItems,
      item: "",
      id: uuidv4(),
      editItem: false
    });
  };
  ...
  render() {
    return (
            <TodoInput
              item={this.state.item}
              handleChange={this.handleChange}
              handleSubmit={this.handleSubmit}
              editItem={this.state.editItem}
            />
            <TodoList
              items={this.state.items}
              clearList={this.clearList}
              handleDelete={this.handleDelete}
              handleEdit={this.handleEdit}
            />
    );
  }
}
export default class TodoItem extends Component {
  state = {
    avatarURL: '',
  }

  componentDidMount() {
    imgGen().then(avatarURL => this.setState({ avatarURL }));
  }

  render() {
    const { title, handleDelete, handleEdit } = this.props;
    const { avatarURL } = this.state; 
    return (
        <h6>{title}</h6>
          <span className="mx-2 text-success" onClick={handleEdit}>
          </span>
          <span className="mx-2 text-danger" onClick={handleDelete}>
          </span>
    );
  }
}
AdamKniec
  • 1,607
  • 9
  • 25
Shachar Oren
  • 45
  • 1
  • 7

4 Answers4

3

You can do it like this, mind the comments

class App extends Component {
  state = {
    // load items while initializing
    items: window.localStorage.getItem('items') ? JSON.parse(window.localStorage.getItem('items')) : [],
    id: uuidv4(),
    item: "",
    editItem: false
  };
  handleChange = e => {
    // ...
  };

  handleSubmit = e => {
    e.preventDefault();
    const newItem = {
      id: this.state.id,
      title: this.state.item
    };
    const updatedItems = [...this.state.items, newItem];

    // Save items while changing
    window.localStorage.setItem('items', JSON.stringify(updatedItems));

    this.setState({
      items: updatedItems,
      item: "",
      id: uuidv4(),
      editItem: false
    });
  };
  // ...

  render() {
    return (
      <>
        <TodoInput
          item={this.state.item}
          handleChange={this.handleChange}
          handleSubmit={this.handleSubmit}
          editItem={this.state.editItem}
        />
        <TodoList
          items={this.state.items}
          clearList={this.clearList}
          handleDelete={this.handleDelete}
          handleEdit={this.handleEdit}
        />
      </>
    );
  }
}
Hao Wu
  • 17,573
  • 6
  • 28
  • 60
1

Here's some simple logic you can use in your componentDidMount() method of your App.

const localStorageList = localStorage.getItem('todo-list')

if (!localStorageList) {return null} else {this.setState({items: localStorageList})

To add to the localStorage please look at this question

and this resource

Bluefire
  • 11
  • 2
1

Let me help you with this, using the least no. of codes. I have written a clear explanation of the steps, for you all to better understand, please bear with me , it is definitely with the time to read.

Also, note this solution is perfectly crafted for functional components. However I have mentioned how to do it in class components, you have to tweak some things if you are using class components. Like you can not use hooks in class-based components, but access this instance, so it will be fine, either ways

Please give it a full read, if you are having a tough time understanding the functionality, I have tried to break down the process in layman. The explanation is long, the lines of code is just under 10. happy to help

Persisting states of the todo app, upon page refresh, is pretty simple. We can use State management libraries for it, or local storage as well. Here, we will just go with the most simple one - using local storage.

Before we jump to the code, let us build the functionality visually. So, after the user enters things in the todo space, we want few things to happen:

  1. We want to store the list of items (which will essentially be an array) in the local storage. (We can skip the JSON.parse, here, since the array that will be saved, will be string, bcz user enters string in the todo-app, generally, however, it's not a bad idea to parse the userinputs).

useEffect(()=>{

   window.localStorage.setItems("key" , value)
   
   }, [dependency])

After you do this, make sure you check the dev-tools => application => localStorage => to see if the key and values are being stored. You shall be able to see them. However, you will notice, that upon refresh, the localStorage values stay, but the data in the UI are lost. Not surprising.

  1. This is the last and important step. What we want upon page reload? Let us break it down :
  • We want to check if there is any data that is there in the localStorage. If there is: we will change the state of the app, based on the previous user inputs.

  • If there is no data in the LocalStorage, we will just pass an empty array.

Using hooks, in the functional component is actually What I prefer, class components require many boiler plates, so, the code...

import {useState} from 'react';/for functional components
//for class components you can just init the state , in the constructor(props) and 
  change it using the this.setState method

  //to getItems from localStorage to render in the UI

   useEffect(()=>{
  const storedData = localStorage,getItems("keys" , value)
  storedData ? setValue(value) : [];
  },[])
  
  [] : because we want it to render on every reload, once.
  smake sure to initiliaze the state using useState;
   const [value , setValue] = useState("")

 //to setItems in localStorage

   useEffect(()=>{

   window.localStorage.setItems("key" , value)
   
   }, [dependency])
    

useEffect is essentially a hook for functional components which is similar to componentDidMount in-class components. If using class components, instead of using the useState, hook, use this.setState.

  • For people who are having trouble to under the ?/: => they are ternary operators, which means:: if(storedData){setValue(storedData)} ; else{ //pass an empty array}. Ternary operators jusr reduces the loc, and it is good to use it sometimes. – Dwaipayan Chakroborty May 15 '21 at 05:04
0

You could format your todolist into a JSON string and store it using :

localStorage.setItem("todolist", "your_JSON_string_here");

However, web Local Storage have storage limitations which will cause issues if the data stored are getting larger in time. More info at here

Perhaps you could consider IndexedDB (if you are storing huge data) INFO

HanKeat
  • 104
  • 5