Mobx和React Hook的结合

7,307 阅读2分钟

在看这边文章前请确保你已经熟悉Mobx和React Hook了。

Hooks 彻底地改变了我们在React中编写函数组件的方式

Hooks 给我们编写函数组件带来了极大的便利, 结合像Mobx这样的状态管理库,我们可以很容易的管理项目中的状态, 并且再也不需要写class组件了!!

对于React, 我们通常使用 mobx-react 包。在使用hooks编写组件时,我们需要使用另一个包 mobx-react-lite。这个包给我们提供了一些自定义hooks,使得我们可以在组件中直接创建observables。

这里有一个简单的例子:sandbox

export const App = observer(() => {
  const store = useObservable({
    todos: [
      { id: 1, text: 'Buy eggs', completed: true },
      { id: 2, text: 'Write a post', completed: false }
    ],
    toggleTodo(index) {
      store.todos[index].completed = !store.todos[index]
        .completed
    },
    get remainingTodos() {
      return store.todos.filter(t => !t.completed).length
    }
  })
  return (
    <div className="App">
      <h2>A Todo App yet again!</h2>
      <TodoList
        todos={store.todos}
        toggleTodo={store.toggleTodo}
      />
      <Footer
        remaining={store.remainingTodos}
        total={store.todos.length}
      />
    </div>
  )
})
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

useObservable Hook 给我提供了一种新的方法在一个对象中同时创建多个observables,actions以及computed属性。组件所需的值可以在这个对象中获取到,并且组件会响应observer包装的值的改变。

现在你可能在想,如果我想在组件间共享状态怎么办呢? mobx-react-lite并没有提供一个Provider组件,但是我们不需要再像React中使用它了!我们有一个替代方案--Context!

Context 是一种可以让我们不需要通过用状态提升或传递来实现状态在多个组件中共享的方案。React提供了一个新的Hook Api来帮助我们在多个组件中共享状态: useContext。 如果你还不了解Context,可以参考官网:Context

下面是同一个例子,在这里我们将Mobx store定义为一个类,然后通过context使用它: sandbox

import { createContext } from 'react'
import { decorate, observable, computed } from 'mobx'

export class Todos {
  todos = [
    { id: 1, text: 'Buy eggs', completed: true },
    { id: 2, text: 'Write a post', completed: false }
  ]

  get remainingTodos() {
    return this.todos.filter(t => !t.completed).length
  }

  toggleTodo = index => {
    this.todos[index].completed = !this.todos[index]
      .completed
  }
}

decorate(Todos, {
  todos: observable,
  remainingTodos: computed
})

export default createContext(new Todos())

-------------------------------------------
export const App = observer(() => {
  const store = useContext(TodoStore)
  return (
    .................
  )
})

在TodoStore.js中,你可以看到要怎么定义一个的Mobx store。 我们直接将创建的context对象返回出去,这要我们就可以很轻松的在多个组件中共享状态了

------------------------2020/4/13更新------------------------

如果需要使用Provider全局注入的store,可以使用inject的形式直接进行注入

import { inject } from "mobx-react";
import { observer } from "mobx-react-lite";

const component = inject(xxxBussiness)(observer(props => {
    

}))

值得注意的是mobx-react 5.3.6版本的observer api还不支持hook的写法,6.x的版本里已经支持hook的写法。所以如果使用的是5.x的版本,需要使用mobx-react-lite的observer api