-
-
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> |
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.
Would you set a this.ws.close() inside your componentWillUnmount() and send a message to 'unsubscribe' in the cable?