useEffect用来监听组件间通信——订阅发布拿不到数据
1.在做这个图书订阅管理系统时,遇到一个这样的业务逻辑:
就是这样的逻辑:: 点击设置---》红色框里选择书籍---》点击提交按钮--》轮播图展示
也就是实现:在蓝色框第一次挂载时订阅也就是‘/admin’页面(图左),点击设置按钮,显示下面的红色框组件,在红色框组件选择要轮播的数据,点击提交按钮,在获取所选的全部数据后,进行发布(图右),并跳转到admin页面。
2.订阅采用useEffert监听,关于useEffert(https://www.jb51.net/article/258465.htm),简要介绍一下
useEffert(第一参数,第二参数),第一参数是一个逻辑处理函数()=>{这里面写数据处理逻辑},也称副效应函数,且允许返回一个函数在组件卸载时执行,多用来清除定时器、计时器、订阅
第二参数为第一参数提供依赖项,分为3种情况:啥也不写,useEffect()每次渲染都执行;[],第一次渲染的时候执行一次就不会再执行;[变量],当变量发生变化的时候执行
这是订阅的代码,没有啥问题,页面挂载的时候,订阅,卸载的时候取消订阅(这是useEffert的取消副作用)
const [imgs, setImglist] = useState([{ id: '001', name: "示例1", author: '示例1', publisher: '示例1', img: '' }]); useEffect(() => { let token = PubSub.subscribe('imgs', (msg, data) => { console.log(msg, data) setImglist(data) }) console.log(token) return () => { console.log(token); PubSub.unsubscribe(token); } }, [imgs])
这是发布的代码,单击按钮时发布
const toRatotionChart = ()=>{ console.log(imgList) PubSub.publish('imgs',imgList); // navigate('/admin') }
我遇到的情况是,当加入return () => { console.log(token); PubSub.unsubscribe(token); }时,代码就不会进入到订阅的第一参数,导致获取不到数据。去掉,又会产生很多的订阅,逻辑上就是不能去掉的。
解决办法,找了很久,通过不断地新测试,发现useEffect的使用,在AB组件通信时,A订阅,B发布,当B跳向A所在的页面时,A不会刷新的情况下,上述合理的代码才会正常让A拿到B发布的数据,也就是说当useEffect在A中监测B发布数据的变化时,A组件必须一直在,订阅的时候在页面上,B跳向他的时候也必须在页面上,让A组件自身与B组件出现的区域在同一页面上成同级关系,这样A不会刷新,之前对应产生的订阅Id就对应上了。
以上图为例子,蓝色框代表A,红色框代表B,如果这个红色框B在新的页面,A通过上面的代码是拿不到数据的,因为这个时候,红色框组件点击提交后要跳转到蓝色框A组件,A被重新渲染了,又重新订阅了一次,而每一次订阅应该是不同的,A第一次给的是uid0,但是当接受的时候A已经变成uid1了,它自然拿不到uid0的数据。
这是针对这种现象的个人理解,效果有效,如果届时不对,麻烦指正,感谢