protonemedia / laravel-splade

💫 The magic of Inertia.js with the simplicity of Blade 💫 - Splade provides a super easy way to build Single Page Applications (SPA) using standard Laravel Blade templates, and sparkle it to make it interactive. All without ever leaving Blade.
https://splade.dev
MIT License
1.47k stars 111 forks source link

Pusher notifications are shown multiple times after navigating within Splade #443

Open J87NL opened 1 year ago

J87NL commented 1 year ago

Description:

Initially, after a hard refresh, when a new event is broadcasted the notification is shown once, as expected. But when I navigate within my Splade app (with <Link ...>'s) and a event is broadcasted, it shows up multiple times:

afbeelding

Posted all relevant code below. Followed documentation as described at https://splade.dev/docs/x-event#Toast%20on%20event In the Pusher Dashboard the event exists only once. I hope someone knows a possible solution for this!

Steps To Reproduce Issue:

Installed with composer:

                "pusher/pusher-php-server": "^7.2",

Installed with NPM:

                "laravel-echo": "^1.15.1",
                "pusher-js": "^8.0.2",

resources/views/layouts/app.blade.php:

                <x-splade-event private channel="admins" listen="AdminUpdate" />

In config/app.php I uncommented:

        App\Providers\BroadcastServiceProvider::class,

routes/channels.php:

<?php

use App\Models\User;
use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('admins', function (User $user) {
    return $user->hasRole('admin');
});

app/Observers/ReactionObserver.php:

<?php

namespace App\Observers;

use App\Events\AdminUpdate;
use App\Models\Reaction;

class ReactionObserver
{
    public function saved(Reaction $reaction): void
    {
            $reaction->loadMissing('ticket');

            event(new AdminUpdate(__('New reaction to: [:slug] :title', [
                'slug' => $reaction->ticket->slug,
                'title' => $reaction->ticket->title,
            ])));
    }

app/Events/AdminUpdate.php:

<?php

namespace App\Events;

use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use ProtoneMedia\Splade\Facades\Splade;

class AdminUpdate implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    protected string $text;

    public function __construct(string $text = '')
    {
        $this->text = $text;
    }

    public function broadcastOn(): array
    {
        return [
            new PrivateChannel('admins'),
        ];
    }

    public function broadcastWith(): array
    {
        return [
            Splade::toastOnEvent($this->text)
                ->rightBottom()
                ->autoDismiss(0),
        ];
    }
P-James commented 1 year ago

This happens because as you navigate around the app the Echo callbacks get re-registered. I don't know how to fix it in Splade, but this might help someone who does.

I had a similar issue on an inertia repo, where I had created a Vue composable useOnEvent that was getting re-registered because of where it was called (I think it was in a layout component or something like that, I can't remember exactly).

If you console.log window.Echo, check the event callbacks, then navigate around and check again, you'll see it ticks up. Like here, I have 3 callbacks for each event, where there should only be 1.

CleanShot 2023-09-02 at 11 02 38