从hr口中了解react的状态管理库(mobx, recoil), 立马过来学习之mobx

了解完Recoil后,立刻来学习了mobx,趁热打铁。

如果想要在react中使用mobx,我们需要安装mobx-react或者mobx-react-lite

  • 如果只想在函数式组件中使用mobx,那么只需要安装mobx, mobx-react-lite
  • 如果想要在类组件或者函数式组件中使用mobx,那么需要安装mobx, mobx-react

mobx

MobX 帮助你以一种简单直观的方式来完成工作,并且mobx中的每一个store都只能被初始化一次

mobx初体验

 // store.jsimport { makeObservable, action, observable, computed } from 'mobx'class Num {constructor() {makeObservable(this, {// 让其成为可响应式的属性num: observable,// action: 表示指定该方法是一个action方法,不让控制台报警告// bound: 表示自动绑定该方法的thisup: action.bound,down: action.bound,// computed: 表示当前值是一个计算值。会存在缓存double: computed})}num = 0up() {this.num++}down() {this.num--}get double() {return this.num * 2}}export default new Num() 
 // 使用store的值import React from 'react'import { observer } from 'mobx-react'import Num from '../store/index'function Test() {return (<div className="App"><p>{Num.num}</p><p>{Num.double}</p><button onClick={Num.up}>增加</button><button onClick={Num.down}>减少</button></div>)}export default observer(Test) 

mobx的一些概念

State(状态)

状态 是驱动应用的数据。 就是我们通过mobx管理的数据。

Derivations(衍生)

任何 源自状态并且不会再有任何进一步的相互作用的东西就是衍生。

MobX 区分了两种类型的衍生:

  • Computed values(计算值)。它们是永远可以使用纯函数(pure function)从当前可观察状态中衍生出的值。感觉他特别像vuex中的getter。
  • Reactions(反应)。Reactions 是当状态改变时需要自动发生的副作用。需要有一个桥梁来连接命令式编程(imperative programming)和响应式编程(reactive programming)。或者说得更明确一些,它们最终都需要实现I / O 操作。

如果你想创建一个基于当前状态的值时,请使用 computed

Actions(动作)

动作 是任一一段可以改变状态的代码。用户事件、后端数据推送、预定事件、等等。 就是更新mobx管理的state。

mobx常见api讲解

observer

如果我们想在组件中使用mobx定义的state等,我们就需要使用observer将组件包裹。

注意这个高阶函数是在react-mobx库中的。

export default observer(Test) 
makeObservable

定义store中属性和动作的配置。

 makeObservable(this, {// 让其成为可响应式的属性num: observable,// action: 表示指定该方法是一个action方法// bound: 表示自动绑定该方法的thisup: action.bound,down: action.bound,// computed: 表示当前值是一个计算值。会存在缓存double: computed})} 
observable

让store中的数据成为可响应式的属性。

action

表示指定该方法是一个action方法。

bound

表示自动绑定该方法的this。省去我们在使用时给该方法绑定this。

computed

表示当前值是一个计算值。会将值进行缓存。当依赖的state发生变化后,自动计算,并重新缓存。

makeAutoObservable

我们知道,在定义完state或者action以后,我们需要配置他们,让其成为一个可响应式的数据或者一个action,这就很麻烦了。

但是这个api可以自动推断我们的state和action,并自动进行配置。

  • 所有的属性都成为observable
  • 所有的方法都成为action
  • 所有的gey都成为computed

并且可以通过后续的参数来排除一些默认的这个配置。

// 第二个参数表示不适用他的默认推导,所以点击减号就会报错
// 第三个参数表示自动绑定this
 makeAutoObservable(this, { down: false }, { autoBind: true }) 

监听属性

autorun

自动收集使用的依赖,然后进行监听。

默认页面加载就会执行一次,当使用的state依赖发生变化,可以执行。类似于vue中的watchEffect。

autorun(() => {console.log('自动收集依赖,然后执行...', num1.num)
}) 
reaction

不会立刻执行,当监听的依赖变化时才会执行。类似于vue中的watch。

 reaction(() => num1.num,() => {console.log('指定依赖,然后监听执行...', num1.num)}) 

mobx处理异步更新

异步操作在mobx中不需要任何特殊处理,因为不论是何时引发的所有reactions都将自动更新。

异步直接操作action方法不会有问题,数据一样会被响应。但是控制台会报警告。

 // 异步操作increment() {setTimeout(() => {this.num++})} 
 configure({enforceActions: 'never'}) 

以上这种方式不推荐。不要直接在action函数中异步修改state。

正确解决异步操作
  • 通过定义一个额外的函数来充当中介,调用action函数。
// 正确的异步:方式一incrementAsync() {setTimeout(this.up, 1000)} 
  • 通过runInAction来异步更改state。
 // 正确的异步,方式二incrementAsync() {setTimeout(() => {runInAction(() => {this.num++})}, 1000)} 

对于多个store,如何优雅的使用

我们在一个组件中可能会使用多个store中的state。所以,为了避免多次导入不同的文件,我们可以有以下处理方式

  • 定义一个统一的store出口文件,将store统一导出。
 // store/index.jsimport a from './aStore.js'import b from './bStore.js'export {a, b} 
  • 通过react提供的context
 import { createContext, useContext } from 'react'import a from './aStore.js'import b from './bStore.js'class RootStore {a = ab = b}const store = new RootStore()const context = createContext(store)export default function useStore() {return useContext(context)} 

第一种方式是我们开发中常用的方法。

做一个异步小demo来测试

// person.jsimport axios from 'axios'import { makeAutoObservable, runInAction } from 'mobx'class Person {constructor() {makeAutoObservable(this, null, { autoBind: true })}person = {}getPersonInfo() {runInAction(async () => {const res = await axios('http://myjson.dit.upm.es/api/bins/irav')this.person = res.data})}}export default new Person() 
// 组件使用import { observer } from 'mobx-react'import React from 'react'import person from '../store/test2'function Test2() {return (<div><h1>展示个人信息</h1><p>{person.person.name}</p><p>{person.person.age}</p><button onClick={person.getPersonInfo}>点击获取</button></div>)}export default observer(Test2) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值