Mobx React  最佳實踐

Dominic_Ming發表於2017-12-21

如果你不知道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);
複製程式碼

mobxjs/mobx-react

只有在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的屬性就是你的介面所得。

傾向於編寫可控元件

多編寫可控元件,這樣會大大降低你的測試複雜度,也讓你的元件易於管理。

Forms – React

作者:Daniel Bischoff

原文:Mobx React — Best Practices

翻譯:Dominic Ming

相關文章