Mobx-State-Tree 学习起手式

2,891 阅读3分钟

对于大型前端项目来说,状态管理是一个非常重要的问题。处理数据,并不困难,困难的是如何把项目中这么多的数据处理的漂亮、简单、好理解。当不同页面拿到同一个数据时,要确保两边的数据是相同的,而不会因为请求的延迟导致两边的数据是不相同的。因此,使用一个统一的状态管理工具是非常有必要的。目前 React 的主流状态管理方案是:Redux 和 Mobx。而 Mobx-State-Tree 则是 Mobx 的开发者开发的又一状态管理工具,Mobx State Tree在保留Mobx基本设计理念的同时结合了Redux只有一个store和不可变数据的优点。

安装

//在 react 项目中使用
npx create-react-app mst-demo-1
// 安装
yarn add mobx mobx-react-lite mobx-state-tree

基础概念

核心思想

Root 树。该树由可变的但受严格保护的对象组成,这些对象富含运行时类型信息。换句话说; 每棵树都有一个形状(类型信息)和状态(数据)。从这棵活树中,会自动生成不可变的结构上共享的快照。 image.png

可以看到,整个项目的状态相当于是一颗树,Root 作为这颗树的树干,在 Root 树上又挂载着其他不同的树枝(其他的状态数据)。也就是说,不同的树枝处理不同的数据,最后将这些数据统一挂载到 Root 树上,因此,可以通过这个 Root 来访问、更新、修改挂载在上面的所有的数据。

基础概念:

树 = type + state

// type
const Todo = types.model({ 
    title: types.string 
})
//state
const coffeeTodo = Todo.create({ 
    title: "Get coffee" 
})

起手式

定义模型

import {types} from "mobx-state-tree"
//定义 List 这个”树枝“的结构,是一个包含 title 属性的对象
const List = types.model({ title: types.string })

创建 Root 树,并初始化数据

// 首先需要定义 Root 树的模型
const RootModel = types.model({
    lists: List
})
// 初始化数据
const rootStore = RootModel.create({
    lists: {
        title: 'hello world'
    }
})

修改状态

const Todo = types.model({ 
    title: types.string 
})
.actions(self => {
    return {
        setNewTitle(newTitle){
            self.title = newTitle
        }
    }
})

//使用
rootStore.lists.setNewTitle('hello ccc')

向一个对象中添加数据

const RootModel = types
  .model({
    userList: types.map(List)
  }).actions(self => {
    return {
      addUser(id: string, title:string, done: boolean){
        self.userList.set(id, List.create({title, done}))
      }
    }
  });

let initialState = RootModel.create({
  userList: {}
});

//调用
rootStore.addUser('1', 'ccc', false)
rootStore.userList.get('1').toggle()

向一个数组中添加数据

const RootModel = types
  .model({
    listArray: types.array(List)
  })
  .actions(self => {
    return {
      addArray(title: string, done: boolean){
        self.listArray.push({title, done})
      }
    }
  });

//调用
rootStore.addArray('dog', false)

异步操作

const RootModel = types
  .model({
    data: types.string
  })
  .actions(self => (
    {
      getData: flow(function* getData(){
        const data = yield axios('http://xxxx')
        self.data = JSON.strinfy(data)
      })
    }
  ));
  
//调用
rootStore.getData()

在 UI 中对 store 进行监听

import {observer} from 'mobx-react-lite';

const User = observer(() => {
  const store  = useRootStore()
  return(
    <div>
      <p>{JSON.stringify(store)}</p>
    </div>
  )
})

export default User

通过快照进行更新

//当 rootStroe 改变时,快照就会改变,使用 onSnapshot 来进行监听和记录
onSnapshot(rootStore, snapshot => {
  console.log('Snapshot: ', snapshot);
});

类型概述

基础类型

  • types.string - 字符串类型
  • types.number - 数字类型
  • types.integer - 整数类型
  • types.boolean - 布尔类型
  • types.Date - 日期类型
  • types.custom - 创建一个自定义基本类型

复杂类型

  • types.model() - 用来描述对象的形状
  • types.array(type) - 声明指定类型的数组。
  • types.map(type) - 声明指定类型的映射。
  • types.model() - 创建一个可链接的模型类型,其中每个链接的方法都会产生一个新的类型
    • .named(name) - 克隆当前类型,但给它一个新名称
    • .props(props) - 根据当前类型生成一个新类型,并添加、覆盖指定的属性
    • .actions(self => ...) - 对当前的数据提供一系列操作
    • .views(self => ..) - 计算属性