MobX5&6 + React使用指南

3,175 阅读3分钟

MobX是react的状态管理库之一。相比Redux有mutation, action, dispatch等概念. mobx则更加简洁, 更符合对store增删改查的操作概念。在eact的版本迭代中,mobx也经历了数次更新迭代。它们的版本兼容性问题,以及mobx的使用问题,想必初学者都会踩坑。下面将对这些问题一一梳理。

核心概念

首先,来快速过一遍mobx5的核心概念。Mobx5中文文档

observable

mobx.observable将对象的属性变为可观察的属性。这里的对象涵盖对象,数组和类实例。写法分为两种:第一种,将有状态的对象用observable包裹起来;第二种,对可观测的属性使用装饰器@observable

observable({
    count: 0
});

class Store {
  @observable count = 0
}

action

mobx.action用来定义更改状态的函数。写法也分为两种。第一种,将改变状态的函数用action包裹起来;第二种,对改变状态的函数加装饰器@action

action(() => {
  store.count++
})

@action setCount = () => {
    this.count++ 
}

observer

observer 函数/装饰器可以用来将 React 组件转变成响应式组件。observer 是由单独的 mobx-react 包提供的。 写法同样也有两种。第一种,将组件用observer包裹起来;第二种,对组件加装饰器@observer

mobx.autorun 包装了组件的 render 函数以确保任何组件渲染中使用的数据变化时都可以强制刷新组件。

observer(function Home () {
  return (
   ...
  )
})

@observer
class Home extends React.Component{
  render () {
    return (
      ...
    )
  }
}

class组件

下面来讲讲针对class组件使用mobx的最佳实践。

Mobx5

在版本兼容性上,Mobx5需要配合react16.x使用。mobx5搭配react17会报错。

Mobx5.x通常采用装饰器的写法,包括@observable, @computed, @action

// store.js
import {observable, action} from 'mobx'
class Store {
  @observable count = 0

  @action setCount = () => {
    this.count++ 
  }
}

export default new Store()

// home.js
import React from 'react'
import {observer} from 'mobx-react'
import store from './store'

@observer
class Home extends React.Component{
  render () {
    return (
      <div onClick={store.setCount}>detail{store.count}</div>
    )
  }
}
export default Home

Mobx6

Mobx6可以配合react17使用。

Mobx6store.js中不需要再写这些装饰器了,直接使用makeObservable或者makeAutoObservable。通常用在类的构造函数中。

makeObservable

makeObservable(target, annotations?, options?) 捕获target对象的属性,并使它们可观察。在class构造函数中,第一个参数为this。

import {makeObservable, observable, action} from 'mobx'

class Store {
  constructor () {
    makeObservable(this, {
      count: observable,
      setCount: action
    })
  }

  count = 0

  setCount = () => {
    this.count++ 
  }
}

export default new Store()

makeAutoObservable

makeAutoObservable(target, overrides?, options?) makeAutoObservable与makeObservable类似,不同点是它会默认推断所有属性,比makeObservable更容易维护。注意:makeAutoObservable不能用于super或subclassed的类。

import {makeAutoObservable} from 'mobx'

class Store {
  constructor () {
    makeAutoObservable(this)
  }

  count = 0

  setCount = () => {
    this.count++ 
  }
}

export default new Store()

函数组件

在react hooks的应用中,hooks的功能已经非常强大,为什么还要用mobx呢?这篇文章讲的比较深入了,感兴趣的童靴点击此链接 Hooks 邂逅 Mobx,代码变得更丝滑了

Mobx5

由于装饰器写法不支持函数式组件,可以用observableobserver函数写法。 mobx5在函数组件的一般用法如下。

import React from 'react'
import { observable } from 'mobx'
import { observer } from 'mobx-react'

const store = observable({
  count: 0,
  setCount: () => {
    store.count++
  }
})

export default observer(function Detail () {
  return (
    <div onClick={store.setCount}>detail: {store.count}</div>
  )
})

Mobx6

Mobx6提供了useLocalObservable, useObserverHOC用法。

useLocalStore已经废弃,官方推荐使用useLocalObservable

import React from 'react'
import {useLocalObservable, useObserver} from 'mobx-react'

export default function Home () {
  const store = useLocalObservable(() => ({
    count: 0,
    setCount () {
      this.count++
    }
  }))
  return useObserver(() => (
    <div onClick={store.setCount}>home{store.count}</div>
  ))
}

除了使用useObserver钩子函数,还可以使用Observer

import React from 'react'
import {Observer, useLocalObservable} from 'mobx-react'

export default function Home () {
  const store = useLocalObservable(() => ({
    count: 0,
    setCount () {
      this.count++
    }
  }))
  return <Observer>
    {
      () => <div onClick={store.setCount}>home{store.count}</div>
    }
  </Observer>
}

最后

以上。表述有误的地方,欢迎童鞋指正。