I'm trying to code a simple Real Time application for my web app. I tried coding it in simple php/blade (using Pusher Cdn), and the programs give the expected results: when the form is submitted, a new event is broadcasted and the other client receives the message. When i try it in Inertia (using Laravel-Echo) all of a sudden, it starts doing some strange things, like rendering (multiple times) the receiver partials, with one single click.
Pusher Cdn and PHP/Blade:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body class="font-sans antialiased">
<div className="grid place-items-center">
<h1 className="text-slate-800 text-center p-8 text-7xl font-bold uppercase">
Test Page
</h1>
<p className="text-slate-500 px-8 text-center mt-3 text-2xl font-bold">
This page is dedicated to test a Real Time Chat in React,
using Laravel Echo and Pusher. Request will be done using
Jquery
</p>
<form>
<button
id='btn'
className="mt-8 text-center border border-slate-800 bg-slate-800 text-white font-bold text-2xl p-3 rounded"
>
Broadcast
</button>
</form>
</div>
<div className="mt-48 grid place-items-center">
<span id="placeholder"></span>
</div>
</body>
<script>
// Enable pusher logging - don't include this in production
Pusher.logToConsole = true;
const pusher = new Pusher("{{ config('broadcasting.connections.pusher.key') }}", {cluster: "eu"});
const channel = pusher.subscribe('public');
channel.bind('chat', function(data){
$.post('/receive', {
_token: '{{csrf_token()}}',
message: "Hello, From JS",
}).done(res => $("#placeholder").last().after(res));
});
$("form").submit(function(e){
e.preventDefault();
$.ajax({
url: '/broadcast',
method:"POST",
headers: {
"X-Socket-Id": pusher.connection.socket_id
},
data: {
_token: "{{ csrf_token() }}",
message: "Hello,From JS"
}
}).done(res => $("#placeholder").last().after(res));
})
</script>
</html>
Inertia (React) and Laravel-Echo:
import React from "react";
import $ from "jquery";
import Echo from "laravel-echo";
import Pusher from "pusher-js";
import { CSRF_TOKEN } from "@/Utils/forms";
function Test() {
window.Pusher = Pusher;
window.Pusher.logToConsole = true;
window.Echo = new Echo({
broadcaster: "pusher",
key: "c804af4b0e3beefe4880",
cluster: "eu",
});
window.Echo.channel("public").listen(".chat", function (data) {
$.post("/receive", {
_token: `${CSRF_TOKEN}`,
message: "Hello, From JS",
}).done((res) => $("#placeholder").last().after(res));
});
const handleSubmit = (e) => {
e.preventDefault();
$.ajax({
url: "/broadcast",
method: "POST",
headers: {
"X-Socket-Id": window.Echo.socketId(),
},
data: {
_token: CSRF_TOKEN,
message: "Hello, From JS",
},
}).done((res) => $("#placeholder").last().after(res));
};
return (
<>
<div className="grid place-items-center">
<h1 className="text-slate-500 text-center p-8 text-7xl font-bold uppercase">
Test Page
</h1>
<p className="text-slate-300 px-8 text-center mt-3 text-2xl font-bold">
This page is dedicated to test a Real Time Chat in React,
using Laravel Echo and Pusher. Request will be done using
Jquery
</p>
<form onSubmit={handleSubmit}>
<button
type="submit"
className="mt-8 text-center border border-slate-800 bg-slate-800 text-white font-bold text-2xl p-3 rounded"
>
Broadcast
</button>
</form>
</div>
<div className="mt-48 grid place-items-center">
<span id="placeholder"></span>
</div>
</>
);
}
export default Test;
Excuse my messy code. As i said above, the problem only occurs when using Laravel-Echo
Expected results:
Client 1: Hello,From JS broadcast
Client 2: Hello, From JS receiver
Actual Results:
Client 1: Hello, From JS receiver; Hello,From JS broadcast
Client 2: Hello, From JS receiver; Hello, From JS receiver
All right, i am publishing what solved it for me in case another developer is having the same issue.
What i've essentialy done, is putting the code responsible for setting up pusher and listening for an event in a useEffect function, with an empty array. I used the useEffect hook to make sure we set up the event listener just once when the component loads. And to keep things tidy, I added a cleanup function in the return statement