I have a rails + react app (separate projects) and I've made an ActionCable websocket for sending simple messages from backend to the frontend. The websocket works, i can see everything on the frontend but I can't see the updates in real-time, only after refresh. I don't know how to implement the real time update.
Here is my code:
import PropTypes from 'prop-types'
import { Switch, Route } from 'react-router-dom'
import actionCable from 'actioncable'
import { DUMMY_QUERY } from 'Queries'
// app/javascript/packs/messages.js
import React, { useState, useEffect } from 'react'
import ReactDOM from 'react-dom'
import MessagesChannel from './channels/messages_channel'
function useForceUpdate(){
const [value, setValue] = useState(0); // integer state
return () => setValue(value => value + 1); // update the state to force render
}
function Dummy() {
const [messages, setMessages] = useState([])
const [message, setMessage] = useState('')
const [rerender, setRerender] = useState(false);
useEffect(() => {
MessagesChannel.received = (data) => {
setMessages(data.messages)
console.log(data)
}
}, [])
/*const handleSubmit = async (e) => {
e.preventDefault()
// Add the X-CSRF-TOKEN token so rails accepts the request
await fetch('http://localhost:3000/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message }),
})
setMessage('')
}*/
return (
<div>
<ul>
{messages.map((message) => (
<li key={message.id}>{message.content}</li>
))}
</ul>
</div>
)
}
export default Dummy
Active cable also hat a frontend component. I have never used it together with react, but with pure js it looks something like that:
Import the lib (consumer.js):
import { createConsumer } from "@rails/actioncable"
export default createConsumer()
Load all channels defined in your repo (index.js):
const channels = require.context('.', true, /_channel\.js$/)
channels.keys().forEach(channels)
Define a js file for each channel (message_channel.js):
import consumer from "./consumer"
consumer.subscriptions.create("MessagesChannel", {
connected() {
// Called when the subscription is ready for use on the server
},
disconnected() {
// Called when the subscription has been terminated by the server
},
received(data) {
// Called when there's incoming data on the websocket for this channel
console.log(data)
}
});
Edit: Just found out there is also a npm package for the frontend components.