You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在数据库新增通知时动态触发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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:45:44