能跑就不要瞎升级,一直不升级,一直爽
最近有个老项目,发现是umi3开发的,去翻了下umi的官网,发现现在官网已经升级到umi4了,甚至还有更进一步的umi max。
因为刚好也不熟悉umi3,umi3和umi4对我来说,都是熟悉的陌生人,后来一想,干脆升级算了,翻了下官网umi3升级umi4也不是很复杂。
没想到这是痛苦的开始,太难了😄
umi3升级umi max的一堆配置错误修改就不赘述了,一把鼻涕一把泪。
好不容易错误修改完,跑起来以后,发现useModel 的使用一直有问题。
吐槽一下,umi的官网只是烂,明明说useModel是自定义hooks,但是官网给出的例子,我不明白为什么不使用use开头。
而且明明是umi max的文档,为什么例子引入useModel还是通过umi引入呢???
真是一头雾水。。。
吐槽结束了,还是书回正题吧
文档说umi max 所做的工作就是将其中的状态或数据变成了全局数据,不同的组件在使用该 Model 时,拿到的是同一份状态或数据。
这里是没有任何问题
目前我项目里边代码是这样使用的,在目录src/models目录下建立一个useUsersModel.ts文件
import React, { useEffect } from 'react';
import { getUsers } from '@/services';
import transform from '../utils/transform';
/**
* 聊天用户map
*/
export default function useUsersModel() {
const [users, setUsers] = React.useState<Map<number, API.User>>(() => {
return new Map<number, API.User>();
});
useEffect(() => {
getUsers().then((res) => {
// setCurrent(undefined);
setUsers(() => {
const map = new Map<number, API.User>();
res.data.forEach((v) => {
map.set(v.id, v);
});
// connect();
return map;
});
});
}, []);
return {
users,
setUsers,
};
// return transform({
// users,
// setUsers,
// });
}
代码很简单,就是简单的一个自定义hooks,在组件里边直接使用useModel就可以直接拿到当前的状态。
这里代码非常简单,就是类似useState的使用方法,但是问题就是出现在setUsers上面,因为我们useModel把我们定义的model文件,给升级成全局的状态。
问题就出现在这里,原来在umi3中是可以使用setUsers进行改变users的状态, 但是我发现当我升级成umi max后,当我使用setUsers 改变users的状态的时候,但是在其它组件里边,使用useModel拿到的状态,仍然是旧的users。
换个说法就是,当我在A组件里边使用setUsers改变users的状态的时候,但是在B组件里边拿到的仍然是users的旧状态。
代码如下:
A组件:
import { useModel } from '@umijs/max';
function A() {
const { users, setUsers } = useModel('useUsersModel');
useEffect(() => {
setUsers(...)
}, [])
B组件:
import { useModel } from '@umijs/max';
function B() {
const { users, setUsers } = useModel('useUsersModel');
useEffect(() => {
// 这里仍然是旧的users,当在A组件修改后,B组件仍然拿不到新的users
console.log(users)
}, [users])
不知道什么原因,我以为umi max 里边useModel把我们在src/models下定义的状态,提取成全局状态后,方法应该也相应的提取成全局方法,行为和umi3是一样的。
但是很显然应该没有。
这里也是我不是很理解的地方,不知道是不是我升级的配置,哪里没有配置对,反正就是状态无法全局更新,不知道是基于什么考虑,为什么不和umi3一样。
官网去翻了下,好像也没相关说明,网上也没找到解决方法,实在不行只能去翻源码。
去翻了下useModel的源码,它这里主要是使用context, 把我们定义的model变成全局的状态,如果想要修改model的状态,需要在model文件里边,二次封装一下。
所以这里需要去把model的文件内容重新定义下,修改src/models/useUsersModel.ts文件
这样修改后,在A组件里边使用setUsers修改状态的时候,B组件就可以拿到最新的状态啦。