Search code examples
reactjslaravelwebsocketreact-reduxlaravel-echo

Prevent duplicate websocket message Laravel Echo and React


I have an app that works using Laravel on the backend, and React on the frontend.

We are using beyondcode/laravel-websockets to broadcast websocket messages from the Laravel server to a React client.

React is able to get the message using the following code:

import Echo from "laravel-echo";

window.Pusher = require("pusher-js");
const options = {
  broadcaster: "pusher",
  key: "...",
  cluster: "...",
  encrypted: false,
  wsHost: process.env.REACT_APP_WSHOST,
  wsPort: 6001,
  forceTLS: false,
  disableStats: true,
  //To be Replace with the Correct URL from ENV
  authEndpoint: `http://${process.env.REACT_APP_APIURL}/laravel-websockets/auth`,
};
const echo = new Echo(options);


function App() {
  //const dispatch = useDispatch();

  echo.channel("ws-test").listen("TestWSEvent", function (e) {
    if (e && e != undefined) {
      let data_o = JSON.parse(e.message).data;
      console.log("socket received",data_o);
        //dispatch(ticketReceived(data_o));
    }
  });

The echo.channel("ws-test").listen(...) section, if it is outside App class, I am getting one message for each broadcast. But if that section is inside App, I am getting two duplicate messages.

React doesn't allow using dispatch outside App class, so since I want to use redux I want the section to be inside App (but there I get the duplicate broadcast message).

What is the reason that I am getting these duplicate messages? What is a good react way to handle this situation?


Solution

  • Ideally you should move the listen function inside a useEffect as we want to create only one listener.

    Presently we will add a new listener for every render of the component.

    useEffect(() => {
      echo.channel("ws-test").listen("TestWSEvent", function (e) {
        if (e && e != undefined) {
          let data_o = JSON.parse(e.message).data;
          console.log("socket received",data_o);
            //dispatch(ticketReceived(data_o));
        }
      });
    }, []);