如何在数据库新增通知时动态触发React的useEffect钩子?
解决通知计数器动态更新问题
首先明确你现有代码的核心问题:
当前useEffect的依赖设为unReadCount,会导致每次调用setUnreadCount后重复触发请求,形成无意义的循环;而且这种方式完全无法感知数据库的新增通知——只有组件挂载或依赖变量变化时才会执行请求,数据库的变更不会主动触发前端更新。
下面是几种可行的解决方案:
方案一:WebSocket 实时推送(推荐)
让后端在数据库新增通知时,主动通过 WebSocket 向接收方客户端推送事件,前端收到推送后直接更新未读计数,无需重复请求接口。
示例代码:
import { useEffect, useState } from 'react'; import io from 'socket.io-client'; const NotificationCounter = () => { const [unReadCount, setUnreadCount] = useState(0); // 初始化WebSocket连接 useEffect(() => { const socket = io('你的后端WebSocket地址'); // 监听新增通知的事件 socket.on('newNotification', () => { // 收到推送后重新获取未读数量,也可直接从推送消息中拿到最新计数 axios.get(USER_API + `api`) .then(res => setUnreadCount(res.data.data)) .catch(err => console.log(err)); }); // 组件卸载时关闭连接,避免内存泄漏 return () => socket.disconnect(); }, []); // 页面初始加载未读数量 useEffect(() => { axios.get(USER_API + `api`) .then(res => setUnreadCount(res.data.data)) .catch(err => console.log(err)); }, []); return ( <> {unReadCount !== null && unReadCount?.length > 0 && ( <View style={{ height: '40%', width: '40%', backgroundColor: '#CF1015', borderRadius: Platform.OS === 'ios' ? '40%' : 23, position: 'absolute', top: -2, justifyContent: 'center', alignItems: 'center', right: -5, zIndex: 100, }} > <Text style={{ fontWeight: 'bold', color: '#F1E3FE' }}>{unReadCount.length}</Text> </View> )} </> ); };
方案二:定时轮询(简单易实现)
通过定时器定期发起请求,获取最新的未读通知数量,适合对实时性要求不高的场景。
示例代码:
import { useEffect, useState } from 'react'; const NotificationCounter = () => { const [unReadCount, setUnreadCount] = useState(0); useEffect(() => { // 封装获取未读数量的函数 const fetchUnreadCount = () => { axios.get(USER_API + `api`) .then(res => setUnreadCount(res.data.data)) .catch(err => console.log(err)); }; // 初始加载数据 fetchUnreadCount(); // 每隔30秒请求一次(可根据需求调整间隔) const interval = setInterval(fetchUnreadCount, 30000); // 组件卸载时清除定时器 return () => clearInterval(interval); }, []); return ( <> {unReadCount !== null && unReadCount?.length > 0 && ( <View style={{ height: '40%', width: '40%', backgroundColor: '#CF1015', borderRadius: Platform.OS === 'ios' ? '40%' : 23, position: 'absolute', top: -2, justifyContent: 'center', alignItems: 'center', right: -5, zIndex: 100, }} > <Text style={{ fontWeight: 'bold', color: '#F1E3FE' }}>{unReadCount.length}</Text> </View> )} </> ); };
方案三:操作完成后主动触发更新
如果当前客户端存在触发通知新增的操作(比如用户发送通知、处理已读通知等),可以在这些操作的回调函数里主动调用获取未读数量的接口,更新计数。
示例代码:
import { useEffect, useState } from 'react'; const NotificationCounter = () => { const [unReadCount, setUnreadCount] = useState(0); // 封装获取未读数量的函数 const fetchUnreadCount = () => { axios.get(USER_API + `api`) .then(res => setUnreadCount(res.data.data)) .catch(err => console.log(err)); }; // 初始加载数据 useEffect(() => { fetchUnreadCount(); }, []); // 假设这是发送通知的函数 const sendNotification = () => { axios.post('发送通知的接口', { /* 通知数据 */ }) .then(() => { // 发送成功后,主动更新未读计数 fetchUnreadCount(); }) .catch(err => console.log(err)); }; return ( <> {/* 计数器UI */} {unReadCount !== null && unReadCount?.length > 0 && ( <View style={{ height: '40%', width: '40%', backgroundColor: '#CF1015', borderRadius: Platform.OS === 'ios' ? '40%' : 23, position: 'absolute', top: -2, justifyContent: 'center', alignItems: 'center', right: -5, zIndex: 100, }} > <Text style={{ fontWeight: 'bold', color: '#F1E3FE' }}>{unReadCount.length}</Text> </View> )} {/* 发送通知按钮示例 */} <Button onPress={sendNotification} title="发送通知" /> </> ); };
最后提醒:你原来的useEffect依赖设置错误,不要把unReadCount作为依赖,否则会引发无限循环,建议改为空数组仅在组件挂载时执行一次初始请求。
内容的提问来源于stack exchange,提问作者bill2
相关产品推荐
相关产品推荐

