mobx with react hook

1,475 阅读2分钟

核心概念(与Hook无关)

1. Observable state(可观察的状态)

mobx 可观察的数据

import { observable } from "mobx";

class Todo {
    id = Math.random();
    @observable title = "";
    @observable finished = false;
}

2. 响应式组件

监听 Observable state 并做出响应更新的组件

const TodoView = observer(({todo}) =>
    <li>
        <input
            type="checkbox"
            checked={todo.finished}
            onClick={() => todo.finished = !todo.finished}
        />{todo.title}
    </li>
)

3. Actions(动作)

改变状态(state)的代码

class VarsStore {
  @action fetchOrder() {}
}

4. 自动响应 - 参考

  • Computed values(计算值)

定义在相关数据发生变化时自动更新的值

class TodoList {
    @observable todos = [];
    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}
  • autorun
  • when
  • reaction

Global Stores

全局数据流

1. Store Class

class VarsStore {
  // 配置数据
  @observable vars = {
    isInit: false
  } as any

	@computed () {}

  @action fetchOrder() {}
  
  ***
}

2. Context with Stores Instance

import React from 'react'
import FileStore from './mobx-file'
import VarsStore from './mobx-vars'

export const storesContext = React.createContext({
  fileStore: new FileStore(),
  varsStore: new VarsStore()
})

3. 提供使用 Hook

import { storesContext } from './mobx-store'

export const useStores = () => React.useContext(storesContext)

4. 具体使用

import { useStores } from '@/store/hooks'

export default observer(({ ...args }: any) => {
  const { varsStore } = useStores()
	
	*****
})

Hooks

1. useLocalStore - 参考

const localStore = useLocalStore(() => ({
    name: "John",
    age: 12
}))

2. useAsObservableSource - 参考

它将外部纯(不包含 getter 或 方法)对象转换为 observable 而后在 useLocalStore 对象 get 中进行引用,这样在外部属性改变时自动通知 useLocalStore 对象对变化进行响应

const observableProps = useAsObservableSource(props)

const person = useLocalStore(() => ({
    name: "John",
    get age () {
    	return observableProps.age
    }
}));

3. useObserver - 参考

包装组件 render 响应数据变化

function Person() {
  const person = useLocalStore(() => ({
    name: "John",
    age: 12
  }));

  return useObserver(() => (
    <div>
      <div>姓名:{person.name}</div>
      <div>年龄:{person.age}</div>
      <button onClick={() => (person.name = "Mike")}>No! I am Mike</button>
    </div>
  ));
}

**

Hoc

1. observer - 参考

将组件包装为响应式组件,以便在可观察对象的值改变后触发页面的重新渲染。

function Person() {
  const person = useLocalStore(() => ({
    name: "John",
    age: 12
  }));

  return <div>
      <div>姓名:{person.name}</div>
      <div>年龄:{person.age}</div>
      <button onClick={() => (person.name = "Mike")}>No! I am Mike</button>
    </div>
  );
}

observer(Person)

Component

1. Observer - 参考

更加细粒度的控制组件的 re-render,特别是针对我们需要传递 render props 给第三方组件的情形,当 render props 内使用了 observable state,这个时候我们需要使用 <Observer> 包裹 render props 的内容

<Observer>{renderFn}</Observer>

使用建议

  1. 组件的中间使用了useObserver钩子,它将在可观察到的更改时重新呈现整个组件。如果要微管理渲染,请随时使用<Observer /> -- 参考 Observer / useObserver 代码对比

  1. 自定义复用 useData
import { useObserver } from 'mobx-react'

// 自定义获取接收者数据
function useCustomerData() {
  const { currCustomer } = useStores()
  return useObserver(() => ({
    customerId: currCustomer.customerId,
    customerName: currCustomer.customerName,
  }))
}

const UserOrderInfo = () => {
  // 这里可以这样用
  const { customerName, customerId } = useCustomerData()
  return (
    <div>
      {customerName} has order {customerId}
    </div>
  )
}

版本适用场景

  • React Hook Class 共存项目
    • mobx-react@6(其包含了 mobx-react-lite)
  • 纯 React Hook 项目
    • mobx-react-lite

参考