我使用React编写了一个小型todo应用程序,用户可以在其中添加和删除项目列表。
作为奖励功能,该列表会保存到localStorage
,因为它已被用户变更,并在组件的初始安装时使用。
在addTodo
和removeTodo
方法中,模式如下:
this.state.todos
localStorage
例如,这是removeTodo
方法:
removeTodo(indexOfItemToRemove) {
const todosCopy = this.state.todos.slice();
todosCopy.splice(indexOfItemToRemove, 1);
this.setState({
todos: todosCopy
});
this.updateLocalStorageWithState();
}
以下是我目前要将this.state.todos
保存到localStorage
updateLocalStorageWithState() {
setTimeout(() => {
localStorage.setItem('localStorageTodos', JSON.stringify(this.state.todos));
}, 1);
}
我发现在不使用setTimeout
的情况下,localStorage
总是落后一步,使用用户可能认为是列表过期版本的内容。
这感觉就像一个黑客。如何在不使用setTimeout
hack的情况下采用相同的方法进行操作?
答案 0 :(得分:2)
setState()
不一定是同步执行的。这会导致您遇到的行为:
setState()
不会立即改变this.state
,但会创建待处理状态转换。在调用此方法后访问this.state
可能会返回现有值。无法保证对
setState
的调用进行同步操作,并且可以对调用进行批处理以获得性能提升。
幸运的是,setState()
接受第二个参数,这是在状态更新完成时调用的回调。您可以使用它来同步本地存储条目:
this.setState({
todos: todosCopy
}, () => {
localStorage.setItem('localStorageTodos', JSON.stringify(this.state.todos));
});
或者,为什么不直接设置本地存储条目而不是先从state
读取?
this.setState({
todos: todosCopy
});
localStorage.setItem('localStorageTodos', JSON.stringify(todosCopy));