cover-img
avatar

托码特人

分享科技与人文

一个关注互联网的技术博客

Mobx使用详解及最佳实践

细说最佳实践

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 的属性就是你的界面所得。

倾向于编写可控组件

多编写可控组件,这样会大大降低你的测试复杂度,也让你的组件易于管理。

参考

作者:Dominic_Ming
链接:https://juejin.im/post/5a3b1a88f265da431440dc4a
来源:掘金

赞赏

声明: 本文内容由托码斯创作整理,由于知识水平和时效性问题,行文可能存在差错,欢迎留言交流。读者若需转载,请保留出处,谢谢!