mobx 学习:hooks 与 mobx 结合
个人结合网上资料总结的一些比较适用的指南
安装
- 会自行安装
mobx-react-lite
npm i -S mobx mobx-react
├─ mobx-react-lite@3.4.0
├─ mobx-react@7.5.2
└─ mobx@6.6.1
Hooks很强大,为何还需要Mobx?
- 依赖传染性 —— 这导致了开发复杂性的提高、可维护性的降低
- 缓存雪崩 —— 这导致运行性能的降低
- 异步任务下无法批量更新 —— 这也会导致运行性能的降低
名词解释:依赖传染性
使用Hooks 编写代码时候,你必须清楚代码中 useEffect 和 useCallback的 “依赖项数组”的改变时机。
有时候,你的 useEffect 依赖某个函数的不可变性,这个函数的不可变性又依赖于另一个函数的不可变性,这样便形成了一条依赖链。一旦这条依赖链的某个节点意外地被改变了,你的 useEffect 就被意外地触发了。
个人理解:你得清楚知道,你的 useEffect/useCallback 类似这种,需要自己维护依赖数组的,每个依赖的触发时机,如果链条过长,就会变得像 OOP 的继承链过长一样的问题。
- 如下: props.a/props.b 如果改变,会引起 console.log 的改变
- 但外面 props.a 什么时候会改变,可能经过一个很长的链条,别人如何使用
Comp1
你无法控制
function Comp1(props) {
useEffect(() => {
console.log('useEffect');
}, [props.a, props.b])
}
名词解释: 缓存雪崩
useRef
可以当成一个数据容器来用- 存储
DOM
只是其中一个用途
换句话说,造成这种原因主要是因为 Hooks 每次都会创建一个全新的闭包,而闭包内所有的变量其实都是全新的。
而每次都会创建闭包数据,而从性能角度来讲,此时缓存就是必要的了。而缓存又会牵扯出一堆问题。
说到底,也就是说没有一个公共的空间来共享数据,这个在 Class 组件中,就是 this,在 Vue3 中,那就是 setup 作用域。而 Hooks 中,除非你愿意写 useRef + ref.current 否则是没有办法找到共享作用域。
个人理解:作者是认为
hook
是一个全新的闭包(每次调用这个函数,是一个闭包,这一点没有错),但多个闭包没有Class
的this
这种共享数据的地方,但React
提供了useRef
这种共享的,他又不想用,所以出现了这个名词。
名词解释: 异步任务下无法批量更新
这个完全没有解释,也不知道他在说明什么问题,以后遇到再回看吧。
那些已经不推荐的
- useLocalStore: 推荐用 useLocalObservable
- useObserver: 推荐使用 <Observer />
- inject: 不确定推荐使用什么,很少用这个api
# 不推荐的
import { useLocalStore } from 'mobx-react';
# 推荐的
import { Observer, useLocalObservable} from "mobx-react";
import React from 'react';
import { useObserver, Observer, useLocalStore } from 'mobx-react';
import { store } from './store';
// 方法1
function Demo1() {
const localStore = useLocalStore(() => store);
return useObserver(() => <div onClick={localStore.setCount}>{localStore.count}</div>)
}
// 方法2 - 官方推荐的方式
function Demo2() {
const localStore = useLocalStore(() => store);
return <Observer>{() => <span>{localStore.count}</span>}</Observer>
}
runInAction使用的必要性?
更新时间点: 2022-08-18 20:21:20
对于这里的用法,不太理解,甚至还没有认同,因为实际测试下来,
store.data = data;
store.loading = false;
只会渲染一次,并不会造成多次渲染,所以,放在
runInAction
的理由到底是什么?
function AppWithMobx() {
const store = useLocalStore(() => ({
data: {},
loading: true,
}))
useEffect(async () => {
const data = await fetchData()
runInAction(() => {
// 这里借助 mobx 的 action,可以很好的做到批量更新,此时组件只会更新一次
store.data = data
store.loading = false
})
}, [])
return useObserver(() => (/* ui */))
}