目前在做一个消息推送的功能,前端框架使用的是Ant Design Pro V5。具体功能就是websocket推一条通知消息过来,前端实时展示。以下是model层的部分代码。
模拟了两条数据,分别为页面加载时发送{ id: 1, msg: '1' }、隔200ms后发送{ id: 2, msg: '2' }。
以前在老版本用的dva数据流,可以通过yield select获取上一次更新后的最新列表数组,然后创一个新数组在原来基础上加上这条新的就ok。现在我也按这个思路写,但是后面第二次调用这个updateNotice时,获取的noticeList还是一个空数组,并没有取到上一次更新后的数据。怀疑可能是异步的问题
目前摸到一种解决方案,在这个model外层建一个tmpList,每次更新先往这里存,再setNoticeList更新到state中。这样写可以解决问题,但是不太优雅,state多了时每个都要建一个tmpList。想请教下大家有没遇到过类似的问题,有没更好的解决方案?
import { useState, useCallback } from 'react';
let tmpList: any = [];
export default () => {
const [noticeList, setNoticeList] = useState<(any)[]>([]);
//更新消息数据
const updateNotice = useCallback((data: { id: number, msg: string }) => {
if (data) {
let result = [...noticeList, data]; //两次noticeList都是空数组
setNoticeList(result);
tmpList = [...tmpList, data];
console.log(result); //第一次是[{ id: 1, msg: '1' }],第二次是[{ id: 2, msg: '2' }]
console.log(tmpList); //第一次是[{ id: 1, msg: '1' }],第二次是[{ id: 1, msg: '1' }, { id: 2, msg: '2' }]
}
}, []);
return { noticeList, updateNotice };
};
附上调用model的部分代码。
import React, { useEffect } from 'react';
import { useModel } from 'umi';
const Notice: React.FC = () => {
const { noticeList, updateNotice } = useModel('notice');
useEffect(() => {
setTimeout(() => { //模拟第一条
updateNotice({ id: 1, msg: '1' });
});
setTimeout(() => { //模拟第二条
updateNotice({ id: 2, msg: '2' });
}, 200);
}, []);
return (
<div>
{noticeList.map((item) => (
<div key={item.id}>
{item.msg}
</div>
))}
</div>
);
};
export default Notice;
已解决。问题出在setNoticeList那里。可能直接在外面取noticeList它是异步的,通过setNoticeList的传参即可取得上一次的更新后的值。感谢各位大神的讨论解答。