2016-11-19 121 views
1

我使用React编写了一个小型待办事项应用程序,用户可以在其中添加和删除项目。避免`setTimeout`'hack'确保状态同步

作为奖励功能,该列表被保存为localStorage,因为它由用户进行了变更,并在组件的初始装载中使用。

addTodoremoveTodo方法两者的图案是这样的:

  1. 设置通过添加或移除this.state.todos
  2. 复制的状态的项localStorage

对于新的状态例如,这里是removeTodo方法:

removeTodo(indexOfItemToRemove) { 
    const todosCopy = this.state.todos.slice(); 

    todosCopy.splice(indexOfItemToRemove, 1); 

    this.setState({ 
     todos: todosCopy 
    }); 

    this.updateLocalStorageWithState(); 
} 

这是我目前在做什么,以节省this.state.todoslocalStorage

updateLocalStorageWithState() { 
    setTimeout(() => { 
     localStorage.setItem('localStorageTodos', JSON.stringify(this.state.todos)); 
    }, 1); 
} 

我发现,不使用setTimeout,在localStorage却总是落后1步,用什么样的用户可能会觉得作为列表的过时版本。

这感觉就像一个黑客。我怎样才能整合一种做同样的事情,而不必使用setTimeout黑客?

+0

'this.setState()'怎么办?有什么'异步'? – Arvind

回答

2

setState()不一定是同步执行的。这将导致您所遇到的行为:

setState()不会立即发生变异this.state但创建待状态转变。调用此方法后访问this.state可能会返回现有值。

无法保证对setState的呼叫进行同步操作,并且可能会调用调用以提高性能。

Source


幸运的是,setState()需要的第二参数,这是一种当状态更新已完成时调用的回调函数。您可以使用您的本地存储条目同步:

this.setState({ 
    todos: todosCopy 
},() => { 
    localStorage.setItem('localStorageTodos', JSON.stringify(this.state.todos)); 
}); 

或者,为什么不设置本地存储条目,而不是直接从state先读?

this.setState({ 
    todos: todosCopy 
}); 

localStorage.setItem('localStorageTodos', JSON.stringify(todosCopy));