React Native 在加载时多次订阅 websocket

问题描述 投票:0回答:1

我是 React Native 的新手,我正在尝试编写一个小应用程序,该应用程序连接到由 Rails ActionCable 提供支持的 Websocket,发送一条消息,然后当我单击“断开连接”时,它会关闭连接并取消订阅频道。

这是我在 React Native 端的代码:

import React, { useState, useEffect, useCallback } from 'react';
import { View, Text } from 'react-native';
import { Button } from 'react-native-paper';
import { ActionCable, Cable } from '@kesha-antonov/react-native-action-cable';
import UUID from 'react-native-uuid';

const actionCable = ActionCable.createConsumer('wss://blabla.ngrok-free.app/cable');
const cable = new Cable({}) 

const App: React.FC = () => {

  //const actionCable = ActionCable.createConsumer('wss://blabla.ngrok-free.app/cable');
  //const cable = new Cable({}) 

  // const channel = cable.setChannel(
  //   `wire_channel_${identifier}`, // channel name to which we will pass data from Rails app with `stream_from`
  //   actionCable.subscriptions.create({
  //     channel: 'WireChannel', // from Rails app app/channels/chat_channel.rb
  //   })
  // )

  const [isWebsocketConnected, setIsWebsocketConnected] = useState(false);
  const [dchannel, setDchannel] = useState();

  const identifier = UUID.v4();
  console.log(identifier);

  const onNewMessage = useCallback(message => {
  }, [])

  const handleReceived = useCallback(({ type, message }) => {
    console.log(type);
    console.log(message);
    console.log("triggered")
  }, [])

  const handleConnected = useCallback(() => {
    setDchannel(cable.setChannel(
      `wire_channel_${identifier}`, // channel name to which we will pass data from Rails app with `stream_from`
      actionCable.subscriptions.create({
        channel: 'WireChannel', // from Rails app app/channels/chat_channel.rb
      })
    ))  
    setIsWebsocketConnected(true)
  }, [])

  const handleDisconnected = useCallback(() => {
    removeChannel()
    setIsWebsocketConnected(false)
  }, [])

  const handleSendMessage = useCallback(() => {
    const channelName = getChannelName(identifier)
    const channel = cable.channel(channelName)
    dchannel.perform('speak', { message: 'Hey', identifier: identifier })
  })

  const getChannelName = (identifier) => {
    return `wire_channel_${identifier}`
  };


  const removeChannel = useCallback(() => {
    const channelName = getChannelName(identifier)
    console.log("getChannelName: "+channelName);

    const channel = cable.channel(channelName)
    console.log(channel);
    if (!channel)
      return

    channel
      .removeListener( 'received', handleReceived )
      .removeListener( 'connected', handleConnected )
      .removeListener( 'disconnected', handleDisconnected )
    channel.unsubscribe()
    console.log(cable.channels)
    delete( cable.channels[channelName] )
    console.log(cable.channels)
  }, [])

  useEffect(() => {
    // channel.on('received', handleReceived);
    // channel.on('connected', handleConnected);
    // channel.on('disconnected', handleDisconnected);

    return () => {
      if(dchannel){
        dchannel.unsubscribe();
      }
    };
  }, []); 

  return (
    <View style={{ flex: 1 }}>
      <View style={{ padding: 20, backgroundColor: '#f0f0f0', alignItems: 'center' }}>
        <Text style={{ fontSize: 24 }}>Your Logo Here</Text>
      </View>
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Button
          mode="contained"
          onPress={handleConnected}
          color="#00C853" // Green color for "Connect" button
          disabled={isWebsocketConnected}
        >
          Connect WebSocket
        </Button>
        <Button
          mode="contained"
          onPress={handleDisconnected}
          color="#FF1744" // Red color for "Disconnect" button
          disabled={!isWebsocketConnected}
        >
          Disconnect WebSocket
        </Button>
        <Button
          mode="contained"
          onPress={handleSendMessage}
          disabled={!isWebsocketConnected}
        >
          Send Message
        </Button>
        <Text>
          WebSocket Status: {isWebsocketConnected ? 'Connected' : 'Disconnected'}
        </Text>
        {/*<Text>Counter: {counter}</Text>
        <View style={{ marginTop: 20 }}>
          <Text>Messages from Server:</Text>
          {messages.map((message, index) => (
            <Text key={index}>{message}</Text>
          ))}
        </View>*/}
      </View>
    </View>
  );
};

export default App;

我遇到的问题是,当应用程序加载时,我看到在服务器端创建了很多订阅,当我单击“发送消息”时,服务器广播多条消息(每个创建的订阅一条消息)。我只想建立 1 个订阅,并且应该仅在我单击“连接 Websocket”按钮时建立。

如何在上面的代码中实现这一点。我已经尝试过多种方法了。

react-native actioncable ruby-on-rails-7
1个回答
0
投票

请删除代码中的 usecallback 挂钩并检查输出。 usecallback 并不适用于每个函数。请检查

React 中的 useCallback 是什么以及何时使用它?

有效使用 usecallback 挂钩。

© www.soinside.com 2019 - 2024. All rights reserved.