十分钟上手Mobx状态管理工具

289 阅读3分钟

引言:为什么选择MobX?

在React项目中使用Redux时,许多开发者都会被其繁琐的模板代码和复杂的概念所困扰。经过多次实践和调研,我发现MobX以其极简的API设计和直观的响应式编程模型,成为了状态管理的优雅解决方案。今天,我将带你全面了解这个高效的状态管理工具。

一、MobX核心概念解析

MobX采用了透明的函数式响应编程(TFRP)模式,其核心架构包含三个关键部分:

  1. State(状态) :应用的数据核心,使用observable标记可观察状态

  2. Action(动作) :修改状态的方法,需用action进行标记

  3. Derivations(派生)

    • Computed values:通过纯函数从状态派生的值
    • Reactions:状态变化的自动响应,用于处理副作用

二、简单使用Mobx

接下来我们先快速使用一下Mobx,完成一个简单的计数器

  1. 下载mobx以及mobx-react
npm install mobx mobx-react-lite
  1. 创建store/counter.ts,通过class创建一个Counter类,添加state和action,computed等,导出counter类
import { makeObservable,observable,action,computed,reaction } from "mobx";

 class Counter{
  count = 0
  constructor(){
    makeObservable(this,{
      count:observable,
      increment:action,
      double:computed,
    })

  }
  increment = ()=>{
    this.count++
  }
  get double(){
    return this.count*2
  }
}

const counter = new Counter()
export default counter
  1. 在组件中使用: 导入store对象,引入observer组件函数包裹react组件:
import { observer } from "mobx-react-lite";
import counter from "./store/Counter";

function App() {
  console.log(1);
  return (
    <>
      <div>{counter.count}</div>
      <div>{counter.double}</div>
      <button onClick={() => counter.increment()}>点击++</button>
    </>
  );
}


export default observer(App); 

Mobx中的副作用

有时候我们需要在状态变化时,做一下小动作,比如:

  • 📝 记录用户操作日志
  • 💾 自动保存数据到本地存储
  • 🌐 发起网络请求

因此我们需要用到派生中的Reaction来完成后续操作: Mobx中一共有三个属性可以使用,分别是: autorun, reaction,when

autorun的使用:

  1. autorun接受一个函数作为参数,每当该函数所观察的值发生变化时,它都应该运行。
  2. autorun在创建时也会运行一次
autorun(()=>{
  console.log('我现在的值是'+counter.count);
})

reaction的使用:

  1. reaction接收俩个参数,俩个参数都接收一个函数,第一个函数的返回值会作为监听值
  2. 第二个函数中接收俩个参数,分别是newValue和oldValue
reaction(()=>counter.count,(newValue,oldValue)=>{
  console.log(newValue,oldValue);
})

when的使用:

  1. 接收俩个参数,在第一个参数返回true时自动调用的一次性副作用,之后停止监听
  2. 返回一个Promise,可用于异步场景
import { when, makeAutoObservable } from "mobx"

class MyResource {
    constructor() {
        makeAutoObservable(this, { dispose: false })
        when(
            // Once...
            () => !this.isVisible,
            // ... then.
            () => this.dispose()
        )
    }

    get isVisible() {
        // 表示此项目是否可见.
        return false
    }

    dispose() {
        // 清理一些资源.
    }
}

Mobx处理异步请求

在实际开发中,异步操作是不可避免的(如接口请求、定时任务等)。MobX提供了灵活的方式来处理异步操作,同时保持状态管理的响应式特性。

核心原则:在异步操作中更新状态时,必须通过action来修改,这能确保所有状态变更都被追踪,并触发相应的响应。

两种处理方式

方式一:将异步操作包裹在action中

import { makeAutoObservable, action } from 'mobx'

class UserStore {
  userData = null
  loading = false
  error = null

  constructor() {
    makeAutoObservable(this)
  }

  // 使用action包装异步方法
  fetchUser = action(async (userId) => {
    this.loading = true
    try {
      const response = await fetch(`/api/users/${userId}`)
      this.userData = await response.json()
    } catch (e) {
      this.error = e.message
    } finally {
      this.loading = false
    }
  })
}

方式二:使用runInAction局部更新

import { makeAutoObservable, action, runInAction } from 'mobx'

class UserStore {
  // ...同上状态定义
  
  fetchUser = async (userId) => {
    this.loading = true
    try {
      const response = await fetch(`/api/users/${userId}`)
      const data = await response.json()
      
      // 在异步回调中使用runInAction
      runInAction(() => {
        this.userData = data
      })
      
    } catch (e) {
      runInAction(() => {
        this.error = e.message
      })
    } finally {
      runInAction(() => {
        this.loading = false
      })
    }
  }
}

在组件中使用

import { observer } from 'mobx-react-lite'
import userStore from './stores/userStore'

const UserProfile = observer(({ userId }) => {
  useEffect(() => {
    userStore.fetchUser(userId)
  }, [userId])

  if (userStore.loading) return <div>Loading...</div>
  if (userStore.error) return <div>Error: {userStore.error}</div>

  return (
    <div>
      <h2>{userStore.userData.name}</h2>
      <p>Email: {userStore.userData.email}</p>
    </div>
  )
})

结语

MobX以其简洁优雅的设计,让状态管理变得直观而高效。通过本文的学习,你已经掌握了从基础使用到高级技巧的全套知识。现在,是时候在你的项目中实践这些技巧了!