I am new to react native and I am trying to write a small app that connects to a websocket, powered by Rails ActionCable, sends a message and then when I click Disconnect it closes the connection and unsubscribes from the channel.
Here is my code on the react native side:
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;
The problem I have is that when the app loads i see a lot of subscription created on the server side and when I click Send Message, The server broadcasts multiple messages (1 per each subscription created). I want to establish only 1 subscription and that should be only when I click the Connect Websocket button.
How can I achieve this in the code above. I have tried multiple things already.
Please remove the usecallback hook in your code and check the output. The usecallback is not for every function. Please check the
for efficient use of usecallback hooks.