Blog>
Snippets

WebSocket Integration for Real-Time Sync

Illustrate how to set up a WebSocket connection with Redux to push and receive state changes in real-time for multi-device synchronization.
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from './reducers';

// Middleware for handling WebSocket actions
const websocketMiddleware = store => next => action => {
  // If the action is to initialize the WebSocket connection
  if (action.type === 'WS_CONNECT') {
    const ws = new WebSocket(action.payload.url);
    // When a message is received from the server
    ws.onmessage = event => {
      const message = JSON.parse(event.data);
      // Dispatch an action with the received message
      store.dispatch({ type: 'WS_MESSAGE_RECEIVED', payload: message });
    };
    // Save the WebSocket object in our action for possible later use
    action.payload.ws = ws;
  }
  // If the action is to send a message through the WebSocket
  if (action.type === 'WS_SEND_MESSAGE') {
    const { ws, message } = action.payload;
    ws.send(JSON.stringify(message));
  }
  // Continue with the next middleware or the reducers
  return next(action);
};

const store = createStore(
  rootReducer,
  composeWithDevTools(applyMiddleware(websocketMiddleware))
);

export default store;
This snippet sets up a Redux store and a middleware to handle WebSocket connections and messages. The middleware checks for specific WebSocket-related actions, establishes a connection if necessary, sets up message handling, and enables the dispatch of messages through the WebSocket.
const wsConnect = url => ({
  type: 'WS_CONNECT',
  payload: { url }
});

const wsSendMessage = (ws, message) => ({
  type: 'WS_SEND_MESSAGE',
  payload: { ws, message }
});
These functions are action creators that return Redux actions for connecting to a WebSocket server and sending messages through an established WebSocket connection.
const initialState = {
  messages: []
};

// Reducer to handle WebSocket messages
const messageReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'WS_MESSAGE_RECEIVED':
      // Add the received message to the state
      return {
        ...state,
        messages: [...state.messages, action.payload]
      };
    default:
      return state;
  }
};

export default messageReducer;
This reducer updates the Redux store's state when a WebSocket message is received, by adding the message to an array of messages.