首页 > 解决方案 > 反应类组件。待办事项应用程序。如何使用 localStorage 存储数据

问题描述

我想用 localStorage 存储待办事项数据,这样刷新页面后它就不会消失。我在开始创建时使用了 React 类组件。

我添加了“handleFormSubmit”和“ComponentDidMount”方法。

  1. 当我输入 todo 并选择日期时,localStorage 中没有任何内容。
  2. 使用 Line 'const result = localData 在 ComponentDidMount 中得到错误?JSON.parse(localData) : [];' :SyntaxError: JSON.parse: JSON 数据第 1 行第 1 列的意外字符
  3. 如何设置和获取项目?

如果我能得到帮助,将不胜感激。我想让这个应用程序真正发挥作用。

import React from "react"
import TodoItem from "./components/TodoItem"
import todosData from "./components/todosData"

class App extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            todos: todosData,
            //setTodos: todosData,
            newItem: "",
            deadline: "",
            editing: false
        }

        this.handleChange = this.handleChange.bind(this)
        this.addTodo = this.addTodo.bind(this)
        this.updateInput = this.updateInput.bind(this)
        this.deleteItem = this.deleteItem.bind(this)
        this.updateItem = this.updateItem.bind(this)
        this.updateDeadline = this.updateDeadline.bind(this)
        this.updateInputDeadline = this.updateInputDeadline.bind(this)
        this.editItem = this.editItem.bind(this)
        this.handleFormSubmit = this.handleFormSubmit.bind(this)
    }

    handleChange(id) {
      this.setState((prevState) => {
        const updatedTodos = prevState.todos.map((todo) => {
          if (todo.id === id) {
            return { ...todo, completed: !todo.completed };
          } else {
            return todo;
          }
        });
        return { todos: updatedTodos };
      });
    }

    addTodo(e) {
      e.preventDefault();
      const newTodo = {
        id: this.state.todos.length + 1,
        text: this.state.newItem,  
        completed: false,
        deadline: this.state.deadline
      }
      const newTodos = this.state.todos.concat([newTodo]);
      this.setState({
        todos: newTodos
      })
    }

    updateInput(value, id) {
        this.setState((prevState) => {
        const updatedTodos = prevState.todos.map((todo) => {
          if(todo.id === id) {
            return {...todo, text: value}
          }else {
            return todo;
          }
        })
        return {todos: updatedTodos}
      })
    }

    updateInputDeadline(value, id) {
        this.setState((prevState) => {
        const updatedTodos = prevState.todos.map((todo) => {
          if(todo.id === id) {
            console.log(value, id);
            return {...todo, deadline: value}
          }else {
            return todo;
          }
        })
        return {todos: updatedTodos}
      })
    }

    updateItem(e) {
      this.setState({
        newItem: e.target.value
      })
    }

    updateDeadline(e) {
      this.setState({
        deadline: e.target.value
      })
    }

    deleteItem(id){
    const filteredItems= this.state.todos.filter(item =>
      item.id!==id); 
      this.setState({
      todos: filteredItems
    })
  }

  editItem(id) {
    this.setState({
      editing: id
    })
  }

  handleFormSubmit() {
    const { todo, deadline } = this.state;
    localStorage.setItem('todo', JSON.stringify(todo));
    localStorage.setItem('deadline', deadline);
  };

  componentDidMount() {
    const localData = localStorage.getItem('todo');
    const result = localData ? JSON.parse(localData) : [];
    const deadlineData = localStorage.getItem('deadline');
    this.setState({ result, deadlineData });

  }

    render() {
        const todoItems = this.state.todos.map
        (item =>
          <TodoItem
          key={item.id}
          item={item}
          handleChange={this.handleChange}
          addTodo={this.addTodo}
          deleteItem={this.deleteItem}
          updateInput={this.updateInput}
          updateInputDeadline={this.updateInputDeadline}
          isEdited={this.state.editing === item.id}
          editItem={this.editItem}
        />)


        return (
          <div className="todo-list">
          <Timer />

          <form onSubmit={this.handleFormSubmit}>
            <div className="add-todo">
              <label>Add an item...</label>
              <input
                type="text"
                name="todo"
                placeholder="Type item here..."
                value={this.state.newItem}
                onChange={this.updateItem}
              />
            </div>

            <div className="date">
              <label htmlFor="deadline">Deadline</label>
              <input
                type="date" id="start" name="deadline"
                min="2021-01-01"
                max="2024-12-31"
                value={this.state.deadline}
                onChange={this.updateDeadline}
              />
            </div>

            <button type="submit" onClick={this.addTodo}>Add to the list</button>
          </form>

            {todoItems.length === 0 ? <p>No items</p> : null}

            <div className="todoitems">
              {todoItems}
            </div>

          </div>
        )
    }
}

export default App

标签: javascriptreactjslocal-storage

解决方案


  1. 当您按下按钮时,您将尝试调用两个事件 - addTodo 和 handleFormSubmit。由于您e.preventDefault()在 addTodo 中调用,因此永远不会调用提交事件。您可以在其中一种方法中执行您需要的所有操作。

  2. 我的猜测是您要么尝试 JSON.parse 一个数组而不是一个对象,要么 的值todo未定义。您正试图todo摆脱this.state,但您只有todos在您的状态下,所以这可能是一个错字。也是如此deadline

  3. 您正在进行设置并正确设置。即使您第一次在构造函数中设置状态,您实际上也可以从 localStorage 获取数据。但是您尝试的 componendDidMount 方法也很好。

constructor(props) {
        super(props)
        const cachedTodos = localStorage.getItem("todo")
        this.state = {
            todos: cachedTodos ?? todosData,
            ...
        }

推荐阅读