I want to create a websocket on demand when certain components want to subscribe to data. How can I share the websocket instance in a redux fashion?
action.js
export function subscribeToWS(url) {
return dispatch => {
let websocket = new WebSocket(url)
websocket.on('connect', () => {
websocket.send("subscribe")
}
websocket.on('message', (message) => {
dispatch(storeNewData(message))
}
}
}
I could do something like this, but this would require a new instance for every new subscription.
The standard place to put things like persistent connection objects is inside middleware. And, in fact, there's literally dozens of existing middlewares that demonstrate that approach, with most of them listed over at https://github.com/markerikson/redux-ecosystem-links/blob/master/middleware.md#sockets-and-adapters . You should be able to use some of those as-is, or at least as examples.
You can look at redux-websocket-bridge
. It unfold Web Socket messages into Redux action, and relay Redux action to Web Socket.
Upside of this approach: you can use Redux on your server as API endpoint, replacing standard REST API with less code.
Also, if your server do not send Flux Standard Action, you can still use redux-websocket-bridge
for raw messages. It works with string
, ArrayBuffer
, and Blob
. Of course, you can always write a small middleware to translate them into Flux Standard Action, e.g. messages from Slack RTM API.
Although this is quite an old question by now, it popped up several times when looking for an example. As @matthewatabet and @abguy mention, https://github.com/luskhq/redux-ws just mentions it has been deprecated and you can use Redux Thunk, without an example specific for web sockets.
For future reference, I found this article that outlines an example, that is implemented in a Github repo, starting on this file. This is for socket.io, but using web sockets directly should be similar.
Summarizing, in the Component call dispatch
with addNewItemSocket
:
<RaisedButton
label="Click to add!" primary={true}
onTouchTap={ () => {
const newItem = ReactDOM.findDOMNode(this.refs.newTodo.input).value
newItem === "" ? alert("Item shouldn't be blank")
: dispatch(addNewItemSocket(socket,items.size,newItem))
{/*: dispatch(addNewItem(items.size,newItem))*/}
ReactDOM.findDOMNode(this.refs.newTodo.input).value = ""
}
}
/>
In the actions file, declare addNewItemSocket
as:
export const addNewItemSocket = (socket,id,item) => {
return (dispatch) => {
let postData = {
id:id+1,
item:item,
completed:false
}
socket.emit('addItem',postData)
}
}
To handle incoming messages from the socket, in the constructor of the component:
socket.on('itemAdded',(res)=>{
console.dir(res)
dispatch(AddItem(res))
})
And in the actoins file, declare AddItem
as:
export const AddItem = (data) => ({
type: "ADD_ITEM",
item: data.item,
itemId:data.id,
completed:data.completed
})
For me this is still new, so any feedback is appreciated. I will also file a PR with https://github.com/luskhq/redux-ws to have an example listed there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With