SignalR + React-Redux
One of the biggest reasons to use Redux is making easy to deal with websockets (check Eric Elliott’s article for more info). SignalR is the Microsoft’s ASP.NET implementation of websockets but different from Socket.IO which work as “messages”, it enables you to call server functions (using their names) on the client side and call client side functions from the server side.
If you are interested in a similar behavior, I wrote a package called Invokr based on Socket.IO which is available on NPM, the package is very simple compared to both (SignalR and Socket.IO) but might be a starting point if you want to be able to write Node.js functions and call them from a client.
This article will only cover how to integrate SignalR with Redux, if you want to get started with SignalR I suggest doing some tutorials at http://www.asp.net/signalr. Also if you are not familiar with Redux get started here: https://egghead.io/courses/getting-started-with-redux
Where to receive my messages?
The key point here is how to “respect” the one direction data flow imposed by Redux. You MUST always call dispatch() with an action for every change that you wanna make on the store.
I’ve saw some implementations where the integration with SignalR lives on the Connector or on the Component (in both cases they were using React, which is the most common scenario). There are several problems with these approachs, but the two biggest are: that every Component or Connector initiates an WebSocket or there is a global declaration of the that is initiated independently of the storage state (i.e: not part of the Redux flow).
Middlewares! I’m sure you already expected this answer. The trick is that middlewares have access to the store and theyare part of the flow for every action called!
So part of your code would be something like that:
This middleware have access to your dispatched action, and it can decide to call any method in your SignalR hub. More than that, it also can access safely your store, therefore you can send more information than what was dispatched. Also, there is only a single hub (that we haven’t defined yet) for the whole app.
Note: the function above use Currying, watch this video to understand it better if the syntax looks confusing.
Now dispatching actions to SignalR is solved, but what about receiving calls from the server?
That can be easily accomplished by creating a “start” function:
In this code, the signalRStart function will receive the store and a callback which is called after the connection to the hub is successfully started.
Within this function you can declare how your “client” function will dispatch actions for every action invoked on the server.
Putting it all together
The last part is calling the signalRStart and attaching the middleware, that can be easily accomplished doing this:
Here we declare the variable that will hold the hub, then we create the store using createStore() and apply the middleware.
After creating the store, we call signalRStart, with store as a parameter and our react render method as the callback.
I’ve omitted all the imports in this code but you can organize those blocks as you prefer.
Following this flow we can make sure that the actions dispatched will have access to the single instace of our hub, avoiding multiple WebSockets opened with the server, also, by using signalRStart we made sure that the client functions will change the store correctly by calling dispatch() and that any of those will only happen if we are connected to the server.
Hope you enjoyed the post!
If you find this post useful please share and like!
If you have any doubts you can find me on twitter @lucavgobbi or send me an email firstname.lastname@example.org