2016-11-19 119 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));