若是你不知道mobx是什麼,請閱讀這篇文章html
在這一篇文章裏,將展現一些使用了mobx的React的最佳實踐方式,並按照一條一條的規則來展現。在你遇到問題的時候,能夠依照着這些規則來解決。react
這篇文章要求你對於mobx的stores有基本的理解,若是沒有的話請先閱讀官方文檔。git
永遠記住,你的stores表明着你的UI狀態,這就意味着,當你將你的stores儲存下來後,就算你關了網頁,再次打開,載入這個stores,你獲得的網頁也應該是相同的。雖然stores並非一個本地數據庫的角色,可是他依然存儲着一些相似於按鈕是否可見,input裏面的內容之類的UI狀態。github
class SearchStore { @observable searchText; @action setSearchText = (searchText) => { this.searchText = searchText } } @observer class SearchInput extends React.Component { handleInputChanged = (event) => { const { searchStore } = this.props; searchStore.setSearchText(event.target.value); } render() { const { searchStore } = this.props; return ( <input value={searchStore.searchText} onChange={this.handleInputChanged} /> ); } } 複製代碼
不建議將REST API請求的函數放在stores裏面,由於這樣以來這些請求代碼很難測試。你能夠嘗試把這些請求函數放在一個類裏面,把這個類的代碼和store放在一塊兒,在store建立時,這個類也相應建立。而後當你測試時,你也能夠優雅的把數據從這些類裏面mock上去。數據庫
class TodoApi { fetchTodos = () => request.get('/todos') } class TodoStore { @observable todos = []; constructor(todoApi) { this.todoApi = todoApi; } fetchTodos = async () => { const todos = await this.todoApi.fetchTodos(); runInAction(() => { this.todos = todos; }); } } // 在你的主要函數裏面 const todoApi = new TodoApi(); const todoStore = new TodoStore(todoApi); 複製代碼
儘可能不要把業務邏輯寫在你的組件裏面。當你把業務邏輯寫在組件裏面的時候,你是沒有辦法來及時定位錯誤的,由於你的業務邏輯分散在各類不一樣的組件裏面,讓你很難來經過行爲來定義究竟是哪些代碼涉及的這個錯誤。最好就把業務邏輯放在stores的方法裏面,從組件裏面調用。bash
請儘可能避免使用全局的store實例,由於這樣你很難寫出有條理而可靠的組件測試。取而代之的是,你能夠使用Provider來把你的store inject到你的component實例的props裏面。這樣你就能夠輕鬆的mock這些store來測試了。markdown
const searchStore = new SearchStore(); const app = ( <Provider searchStore={searchStore}> <SearchInput /> </Provider> ); ReactDom.render(app, container); 複製代碼
請不要直接在組件裏面直接操做store的屬性值。由於只有store纔可以來修改本身的屬性。當你要改變屬性的時候,請使用相應的store方法。否則的話你的屬性修改會散落在各處不受控制,這是很難debug的。async
@observer
在每一個組件聲明的時候使用@observer來更新組件的狀態。否則在嵌套組件裏面,子組件沒有聲明的話,每次狀態更新涉及到的都是父組件級的從新渲染。當你都使用了@observer
時,從新渲染的組件數量會大大下降。ide
@computed
就像下面代碼的例子,使用@computed
屬性來處理一些涉及多個屬性的邏輯。使用@computed
能夠減小這樣的判斷類業務邏輯在組件裏面出現的頻率。
class ApplicationStore { @observable loggedInUser; @observable isInAdminMode; @computed isAdminButtonEnabled = () => { return this.loggedInUser.role === 'admin' && this.isInAdminMode; } } 複製代碼
你不須要使用react router管理狀態。就像我前面所說的,你的store就表明了應用的狀態。當你讓router來管理部份應用狀態的時候,這部分狀態就從store裏面剝離開來。因此儘可能使用store來儲存全部的UI狀態,這樣store的屬性就是你的界面所得。
多編寫可控組件,這樣會大大下降你的測試複雜度,也讓你的組件易於管理。
原文:Mobx React — Best Practices
翻譯:Dominic Ming