React Redux & Websockets

React Redux & Websockets

In the previous year, the popularity of React has grown immense, but so did the frameworks, extensions and patterns to use with React. One I will be picking out in this post is Redux, in combination with websockets. In short Redux is a predictable state container for JavaScript apps such as React and follows the following three principles: 

  1. Single Source of Truth: The state of the application lives all in once place.
  2. State is read-only: State can only be modified through actions.
  3. Changes are made with pure functions: State can only be transformed by pure functions (reducers).

For more information about how it works internally and further documentation about Redux can be found on the Redux website. I will not be going through the parts of Redux and how it can be combined with React.

Now from here I will be going for in-depth details about combining websockets with Redux. In general Redux does not specify a way to retrieve/send data from/to the server with websockets. After spending some time reading about the aspects of React and how I previously used websockets in combination with the Flux pattern I managed to extend Redux in a small way that respects it's principles and is very loosely coupled.

I needed two things to do this:

1. Listen to messages from the server and dispatch them as actions on the Redux store.

At first I started looking at the React Redux documentation and found out that it is possible to import the Redux store and dispatch actions on it from anywhere in the application, without binding the actions to a component. With this I could create a module that exports a function which creates listeners on socket messages, and call dispatch on the store whenever a message is received by importing and using the actions already defined combined with the data received from the socket transaction (see example link on the bottom of the article). So the first I needed was done and respects the Redux principles.

2. Send messages to the server and still being able to update the state of the application.

This one was easier to implement. By default I use a socket client that is already connected on import in any module. This way socket.on and socket.emit can be called from anywhere in the application. By just calling socket.emit on receiving the Redux action that corresponds with it, it is possible to send information to the server. Besides that, state such as search filters could be saved to the store or the application could be updated already (if possible) for better user experience.

Now with this idea implemented, the basic Redux tree is slightly extended by:

  • adding commands, which will contain the calls to the server. This way you separate the actions that are client-only, and actions that go to the server. This idea came up to me when looking at elm architecture. The separation of this concern is important as you progress into a large application. Besides that, you don't want to place server calls in your components as they are a view kind of type, and should not have any knowledge about how to get data. The data is given by the Redux store or a parent component via props.
  • adding listeners besides your client app, actions, commands and reducers. In here you basically place everything you want to listen to from the server. The listeners are always imported in the commands file that corresponds with it, as we make our server calls there. In here the exported function of the listeners are called along with the imported socket in the commands file. The exported function of the listeners contain the calls that bind a callback whenever a certain message is received.

All of this and more can be found in a working code example on my GitHub page. The example is written in combination with React to show a full demonstration about actions through user actions and socket transactions in a todo app. I used material-ui for the user interface components to quickly create a styled application.

- Patrick van Vuuren, Software Developer & Scrum Master @ Proforto

 

 

 

 

I really like the simplicity of your example app. However, reducers should be pure functions, pure functions should not have side effects. Emitting events to a socket is a side effect. Therefore the correct place to put that logic would be inside the middleware. http://redux.js.org/docs/advanced/Middleware.html

To view or add a comment, sign in

More articles by Patrick van Vuuren

Others also viewed

Explore content categories