将阵列状态持久保存到本地存储

时间:2019-12-28 11:20:34

标签: arrays reactjs forms local-storage

我已经用React构建了一个简单的Todo List应用。待办事项列表任务保持在数组on状态。我希望能够在刷新浏览器后保留相同的待办事项列表数组。为此,我尝试在项目中实现本地存储。将待办事项数组设置为本地存储。但是,在插入以下代码后,应用程序中断,并且我收到一条错误消息,指出props.todos.map不是函数。


  componentDidMount() {
    const todos = localStorage.getItem("todos");
    this.setState({ 
      ...this.state.todos, 
      todos });
  }

有人可以通过本地存储代码帮助我解决此问题吗?这是该组件(App.js)的其余代码。我将在下面包含其他组件的代码(以防万一,这有助于我找到答案),但是我可以肯定问题出在上面发布的代码片段中的App.js中。当我评论该片段时,该应用程序将恢复到以前的工作状态,但是显然,我仍然无法保持状态。

App.js:

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      todos: [
        {
          task: "learn how to fly drone",
          id: 1,
          completed: false
        }, 
        {
          task: "learn React class components",
          id: 2,
          completed: false
        },
        {
          task: "practice editing videos",
          id: 3,
          completed: false
        },
        {
          task: "read Ten Years A Nomad",
          id: 4,
          completed: false
        }
    ],
      todo: ''
    }
  }

  inputChangeHandler = event => {
    this.setState({[event.target.name]: event.target.value})
  }

  addTask = event => {
    event.preventDefault();
    let newTask = {
      task: this.state.todo,
      id: Date.now(),
      completed: false
    };
    this.setState({
      todos: [...this.state.todos, newTask],
      todo: ''
    })
    const { todos } = this.state;
    localStorage.setItem("todos", todos);
  }

  toggleComplete = itemId => {
    const todos = this.state.todos.map(todo => {
      if (todo.id === itemId) {
        todo.completed = !todo.completed
      }
      return todo
    });
    this.setState({todos, todo: ''})
  }

  clearCompleted = e => {
    e.preventDefault();
    const todos = this.state.todos.filter(item => !item.completed);
    this.setState({
      ...this.state,
      todos
    })
  }

  componentDidMount() {
    const todos = localStorage.getItem("todos");
    this.setState({ 
      ...this.state.todos, 
      todos });
  }

  render() {
    return (
      <div className="App">
        <div className="header">
          <h2 className="title">Welcome to your Todo App!</h2>
          <TodoForm todos={this.state.todos} value={this.state.todo} inputChangeHandler={this.inputChangeHandler} addTask={this.addTask} clearCompleted={this.clearCompleted}/>
        </div>
        <TodoList 
          todos={this.state.todos} 
          toggleComplete={this.toggleComplete} />
      </div>
    );
  }
}

export default App;

TodoList.js:

const TodoList = props => {
    return (
        <ul className="todo-list">
            {props.todos.map((todo, id) => (
                    <Todo 
                        todo={todo} 
                        key={id} 
                        toggleComplete={props.toggleComplete} 
                    />
            ))}
        </ul>
    )
}

export default TodoList;

Todo.js:

const Todo = props => {
    return (
            <li 
                className={props.todo.completed ? "completed-todos" : "todos"}
                style={{textDecoration: props.todo.completed ? 'line-through' : 'none'}}
                key={props.todo.id}
                onClick={() => {
                    props.toggleComplete(props.todo.id)
                }}
            >
                {props.todo.task}
            </li>
    )
}

export default Todo;

TodoForm.js:

const TodoForm = props => {
    return (
        <form className="add-form">
            <input 
                className="add-input"
                name="todo" 
                value={props.value} 
                type="text" 
                onChange={props.inputChangeHandler} 
                placeholder="Enter new task" />
            <button className="add-button" onClick={props.addTask}>Add Todo</button>
            <button className="clear-button" onClick={props.clearCompleted}>Clear Completed</button>
        </form>
    )
}

export default TodoForm;

1 个答案:

答案 0 :(得分:1)

LocalStorage存储键值对。因此,要存储一个JavaScript对象,您需要使用JSON.stringify( object => String )进行序列化,并从localStorage中检索项目,您需要再次使用JSON.parse(字符串=>对象
因此,如下更改addTaskcomponentDidMount

  addTask = event => {
    event.preventDefault();
    let newTask = {
      task: this.state.todo,
      id: Date.now(),
      completed: false
    };
    this.setState(
      {
        todos: [...this.state.todos, newTask],
        todo: ""
      },
      () => {
        localStorage.setItem("todos", JSON.stringify(this.state.todos));
      }
    );
  };

  componentDidMount() {
    const todos = localStorage.getItem("todos");
    if (todos) this.setState({ todos: JSON.parse(todos) });
  }

这是包含固定版本的临时sandbox