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

React Native+Redux中Pusher频道无法获取最新状态问题

解决pusher-websocket-react-native中onEvent无法获取Redux最新状态的问题

问题场景

在Expo平台使用pusher-websocket-react-native开发实时聊天应用时,订阅presence频道后,Redux store中的selectedChatRoom状态发生变化,但频道的onEvent回调始终只能获取到旧的状态值,导致逻辑判断出错(比如判断当前是否处于对应聊天室时用了旧ID)。

当前解决方案

通过取消订阅后重新订阅频道的方式,让onEvent绑定到最新状态,但这种方式存在额外网络开销,且可能造成短暂的连接中断:

// Current solution
const resubscribeToChannels = async () => {
  if (selectedChatRoom?._id === undefined) return;
  await pusher
    .unsubscribe({
      channelName: `presence-${selectedChatRoom?._id}`,
    })
    .then(async () => {
      await pusher.subscribe({
        channelName: `presence-${selectedChatRoom?._id}`,
        onEvent,
      });
    }
  );
};

useEffect(() => {
  resubscribeToChannels();
}, [selectedChatRoom]);

更优解决方案:使用useRef跟踪最新状态

利用useRef的特性(其current属性在组件生命周期内始终保持最新值),同步跟踪selectedChatRoom的最新状态,无需重新订阅频道即可在onEvent中获取最新值:

实现代码

const { selectedChatRoom } = useSelector(state => state.chat, shallowEqual);
// 创建ref存储最新的selectedChatRoom
const selectedChatRoomRef = useRef(selectedChatRoom);

// 每当selectedChatRoom更新时,同步更新ref的current值
useEffect(() => {
  selectedChatRoomRef.current = selectedChatRoom;
}, [selectedChatRoom]);

const onEvent = (event) => {
  switch (event.eventName) {
    case bindingKeys.chat.message:
      onMessageReceived(event);
      break;
    default:
      break;
  }
};

const onMessageReceived = (event) => {
  const chatRoomId = event.data.chatRoomId;
  // 从ref中获取最新的selectedChatRoom状态
  const isChatRoomOpen = selectedChatRoomRef.current?._id === chatRoomId;
  // ...后续业务逻辑
};

方案优势

  1. 避免重新订阅带来的网络请求和连接中断问题,提升实时性和性能
  2. 逻辑简洁,无需修改频道的订阅状态
  3. 适用于所有需要在异步回调中获取最新状态的场景

注意事项

  • 确保useEffect的依赖数组仅包含selectedChatRoom,避免不必要的ref更新
  • 如果需要跟踪多个状态,可以创建多个独立的ref,或者使用一个对象ref存储多个状态

内容的提问来源于stack exchange,提问作者Afeef

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:25:23