如果你不知道mobx是什麼,請閱讀這篇文章
在這一篇文章裡,將展示一些使用了mobx的React的最佳實踐方式,並按照一條一條的規則來展示。在你遇到問題的時候,可以依照著這些規則來解決。
這篇文章要求你對於mobx的stores有基本的理解,如果沒有的話請先閱讀官方文件。
stores 代表著UI狀態
永遠記住,你的stores代表著你的UI狀態,這就意味著,當你將你的stores儲存下來後,就算你關了網頁,再次開啟,載入這個stores,你得到的網頁也應該是相同的。雖然stores並不是一個本地資料庫的角色,但是他依然儲存著一些類似於按鈕是否可見,input裡面的內容之類的UI狀態。
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請求和store的action分離
不建議將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裡面
儘量不要把業務邏輯寫在你的元件裡面。當你把業務邏輯寫在元件裡面的時候,你是沒有辦法來及時定位錯誤的,因為你的業務邏輯分散在各種不同的元件裡面,讓你很難來通過行為來定義到底是哪些程式碼涉及的這個錯誤。最好就把業務邏輯放在stores的方法裡面,從元件裡面呼叫。
避免使用全域性的store例項
請儘量避免使用全域性的store例項,因為這樣你很難寫出有條理而可靠的元件測試。取而代之的是,你可以使用Provider來把你的store inject到你的component例項的props裡面。這樣你就可以輕鬆的mock這些store來測試了。
const searchStore = new SearchStore();
const app = (
<Provider searchStore={searchStore}>
<SearchInput />
</Provider>
);
ReactDom.render(app, container);
複製程式碼
只有在store裡面才允許改變屬性
請不要直接在元件裡面直接操作store的屬性值。因為只有store才能夠來修改自己的屬性。當你要改變屬性的時候,請使用相應的store方法。不然的話你的屬性修改會散落在各處不受控制,這是很難debug的。
時刻記得在元件宣告 @observer
在每個元件宣告的時候使用@observer來更新元件的狀態。不然在巢狀元件裡面,子元件沒有宣告的話,每次狀態更新涉及到的都是父元件級的重新渲染。當你都使用了@observer
時,重新渲染的元件數量會大大降低。
使用 @computed
就像下面程式碼的例子,使用@computed
屬性來處理一些涉及多個屬性的邏輯。使用@computed
可以減少這樣的判斷類業務邏輯在元件裡面出現的頻率。
class ApplicationStore {
@observable loggedInUser;
@observable isInAdminMode;
@computed isAdminButtonEnabled = () => {
return this.loggedInUser.role === 'admin' && this.isInAdminMode;
}
}
複製程式碼
你不需要 react router 來管理狀態
你不需要使用react router管理狀態。就像我前面所說的,你的store就代表了應用的狀態。當你讓router來管理部份應用狀態的時候,這部分狀態就從store裡面剝離開來。所以儘量使用store來儲存所有的UI狀態,這樣store的屬性就是你的介面所得。
傾向於編寫可控元件
多編寫可控元件,這樣會大大降低你的測試複雜度,也讓你的元件易於管理。
原文:Mobx React — Best Practices
翻譯:Dominic Ming