-
-
Save jevin/414dcdb1b1fe6d5e48c2e9dc53fbc931 to your computer and use it in GitHub Desktop.
# config/routes.rb | |
Rails.application.routes.draw do | |
mount ActionCable.server, at: '/cable' | |
end | |
# app/channels/chat_channel.rb | |
class ChatChannel < ApplicationCable::Channel | |
def subscribed | |
stream_from "chat_channel" | |
end | |
def unsubscribed | |
end | |
def speak(data) | |
ActionCable.server.broadcast("chat_channel", message: "#{data["message"]}") | |
end | |
end |
# Goes inside componentDidMount() in any screen | |
this.ws = new WebSocket('ws://0.0.0.0:3000/cable'); | |
this.channel_name = 'ChatChannel'; | |
this._handleMessage = (data) => { | |
this.setState({ | |
messages: this.state.messages.concat([data.message.message]) | |
}) | |
} | |
this.ws.onopen = () => { | |
const msg = { | |
command: 'subscribe', | |
identifier: JSON.stringify({ | |
channel: this.channel_name, | |
}), | |
}; | |
this.ws.send(JSON.stringify(msg)); | |
}; | |
this.ws.onmessage = e => { | |
var data = JSON.parse(e.data); | |
if (data.identifier != undefined) { | |
data.identifier = JSON.parse(data.identifier) | |
} | |
if (data.type == "welcome" || data.type == "ping" || data.type == "confirm_subscription") { | |
return; | |
} | |
if (data.identifier.channel == this.channel_name) { | |
this._handleMessage(data) | |
return; | |
} | |
}; | |
this.ws.onerror = e => { | |
console.log("ERROR: " + e.message); | |
}; | |
this.ws.onclose = e => { | |
console.log("CONNECTION CLOSED: " + e.code + " " + e.reason); | |
}; | |
this.ws.sendmessage = data => { | |
const msg = { | |
command: 'message', | |
identifier: JSON.stringify({ | |
channel: 'ChatChannel', | |
}), | |
data: JSON.stringify(data) | |
}; | |
this.ws.send(JSON.stringify(msg)); | |
} | |
# Somewhere in the code | |
_sendMessage = (message) => { | |
this.ws.sendmessage({ | |
action: 'speak', | |
message: message, | |
}); | |
} | |
<TouchableOpacity onPress={() => this._sendMessage("Hello world!)}> | |
<Text> | |
Send message | |
</Text> | |
</TouchableOpacity> |
Would you set a this.ws.close() inside your componentWillUnmount() and send a message to 'unsubscribe' in the cable?
Thanks! The whole code needs a refresh. I think you’re right in your this.ws.close() placement.
Thanks! The whole code needs a refresh. I think you’re right in your this.ws.close() placement.
Thanks! The whole code needs a refresh. I think you’re right in your this.ws.close() placement.
Is there anything else you need to do on the rails side to channel.rb or connection.rb?
I guess our ChatChannel inherits from Channel < ActionCable::Channel::Base so that sort of takes care of it. I like this approach instaed of using the action cable npm package on the front end which seems a bit more work than its worth. cheers!
Yeah I don’t think anything else is needed. The idea was to make this Gist as simple as possible.
Like you said, that’s why I’m not using any npm package.
Your "Hello world!" is missing a ending quotation 🙌 Thanks for this 👍