Skip to content

Fix error when there is a single parameter in Livewire.dispatch() #9163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

GC-Max
Copy link
Contributor

@GC-Max GC-Max commented Jan 29, 2025

This pull request addresses an issue that occurs when using Livewire.dispatch() inline without wrapping parameters in an array. Under current behaviour, passing parameters in non-array format leads to a page error.

To replicate the error, you can run the newly added test while disabling Arr::wrap() in the SupportEvents class. This PR ensures that parameters passed to Livewire.dispatch() can be safely handled, regardless of whether they are provided as an array or as individual arguments, thereby preventing the page error.

@joshhanley joshhanley changed the title Fix error when there is a single parameter in Livewire.dispatch() Fix error when there is a single parameter in Livewire.dispatch() May 28, 2025
Copy link
Member

@joshhanley joshhanley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GC-Max thanks for the PR!

For anyone else looking, the error that is thrown is the below.

image

When I tested it, this PR fixes that issue and also allows $this->dispatch('foo', 'bar'); to work. I've pushed an update to the test that includes that.

@joshhanley
Copy link
Member

joshhanley commented May 29, 2025

So I've dug into this a little more and found that this fix doesn't fully fix the issue.

The scenario

Currently if you call $this->dispatch('test', 'new'); from a method in a Livewire component, then it get's picked up correctly by listeners and the event.detail is already an array ['new'].

You can see below, we have 3 listeners (#[On] attribute, x-on:, and @script using $wire.on()) set up and they are all receiving ['new'] correctly.

image

But if we try to dispatch the event using wire:click="$dispatch('test', 'other')", then we can see the two browser based listeners receive the data, but it's like 'other' instead of ['other'] which is what is expected to match what happens above when dispatching from the backend. We can see the backend listener fails all together with an exception.

image
<?php

use Livewire\Attributes\On;
use Livewire\Volt\Component;

new class extends Component {
    public function doSomething()
    {
        $this->dispatch('test', 'new');
    }

    #[On('test')]
    public function random(...$details)
    {
        ray('method listener', $details);
    }
}; ?>

<div>
    <flux:button wire:click="doSomething">Fire from Livewire method</flux:button>
    <flux:button wire:click="$dispatch('test', 'other')">Fire from $dispatch</flux:button>
    <div x-on:test.window="console.log('x-on: listener', $event.detail)"></div>
</div>

@script
    <script>
        $wire.on('test', (detail) => {
            console.log('script listener', detail);
        });
    </script>
@endscript

The problem

The issue is that the front end $dispatch() is actually just using the params directly.

export function dispatch(component, name, params) {

Where as the backend $this->dispatch() is getting the params as an array because of the ...

public function dispatch($event, ...$params)

The solution

The solution proposed in this PR was to wrap the params in an array on the backend if they're not already an array.

The issue with that is that the results are inconsistent depending on whether the event if fired from the backend or the front end (top 2 below is backend and bottom 2 are front end).

image

So instead the fix is to add the check to the frontend, just before the frontend event is dispatched, check to see if the params are a string, and if they are wrap them in an array.

In theory we could update the frontend method signature to include ...params

export function dispatch(component, name, ...params) {

But when I tested this, I found it's actually a breaking change as it causes an extra layer of nesting due to objects being able to be passed into $dispatch() as the params.

Hence why the best solution is to only wrap params if it's a string. I've pushed these changes to the PR.

Now we can see no matter where the event is fired from, if there is only a single value in it, then it will be wrapped correctly.

image

# Conflicts:
#	dist/livewire.esm.js.map
#	dist/livewire.min.js
#	dist/livewire.min.js.map
#	dist/manifest.json
@calebporzio calebporzio merged commit e63b745 into livewire:main May 29, 2025
9 checks passed
@calebporzio
Copy link
Collaborator

thanks a bunch

@GC-Max GC-Max deleted the fix-error-when-with-single-parameter-in-dispatch branch June 4, 2025 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy