Search code examples
laravel-bladevitelaravel-livewirealpine.js

ReferenceError <component> is not defined but running twice with Laravel 10 and Livewire 3.0


I am seeing strange behaviour from an Alpine JS component when running with Laravel 10.20 and Livewire 3.0.0-beta.10. I have a Laravel Blade component that contains an Alpine JS component. The <script> is pushed to a stack in my app.blade.php. In the console, I see "Uncaught ReferenceError: is not defined".

I have created a very basic, contrived Blade (not Livewire) component to demonstrate.

The blade component:

<ul x-data="testApp" x-init='items=@json($items)'>
    <template x-for="(item, index) in items" :key="index">
        <li :idx="index" @click="logItem($event)" x-text="item"></li>
    </template>
</ul>
@once
    @push('scripts')
        <script>
            document.addEventListener('alpine:init', () => {
                Alpine.data('testApp', () => ({
                    items: [],
                    init() {
                        console.log('testApp.init()');
                    },
                    logItem(event) {
                        console.log(event.target.innerText);
                    }
                }));
            });
        </script>
    @endpush
@endonce

The class for the Blade component has the standard render() method and the most basic constructor.

public function __construct(public array $items) {}

The blade that uses the component:

<x-app-layout>
    <div>
        @php
            $items = ['Item A', 'Item B', 'Item C'];
        @endphp
        <x-test :items="$items" />
    </div>
</x-app-layout>

The route to that blade:

Route::get('/dashboard', function () {
    return view('member-dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');

app.blade.php:

<html>
    <head>
        ...
        @vite(['resources/css/app.css'])
        @livewireStyles
    </head>
    <body>
        ...
        @stack('scripts')
        @vite(['resources/js/app.js'])
        @livewireScripts
    </body>
</html>

You can see that I have even tried splitting the default @vite directive, which normally loads the css and js in the <head>. I have also tried the @vite, @stack and @livewireScripts in all possible sequences. None of these has any effect, which, in itself, seems a little odd.

When I load the page, I see the following in the console:

  1. the output from the console.log() within testApp.init()
  2. a warning: "Alpine Expression Error: testApp is not defined" from livewire.js
  3. an error: "Uncaught ReferenceError: is not defined" from livewire.js

On the page, I see the set of three <li> elements duplicated within the <ul>. That is, I end up with six <li> elements:

  • Test A
  • Test B
  • Test C
  • Test A
  • Test B
  • Test C

When I click an item, I see it's innerText appear in the console twice. So, clearly, the testApp object does exist because its logItem method is being called, albeit twice.

This is in a new project that I started, not an upgrade. The same component and approach works fine in a different project with Laravel 9 and Livewire 2.10 (with Alpine JS 3.10) and no Vite.

It is not clear whether the two problems (The Uncaught ReferenceError and duplication of data) are caused by the same underlying issue. I have been through the Liverwire and Laravel upgrade documentation and cannot see anything that appears relevant to explain why this would work with older versions but not with the latest. The other potentially major difference is that I using Vite on the new project.

I am using VS Code and Laragon for development on Windows 11.

UPDATE 12:06 23-Aug-2023

I noticed that the components that are duplicating output are using x-for for their loops. I changed the loop in test blade to use @foreach and I stopped getting the duplication of <li> elements. Unfortunately, I need to use x-for in my actual components. Anyway, I still got the uncaught ReferenceError and, bizarrely, clicking on one of the items still logs two entries in the console.


Solution

  • It turns out that the problems (and another JavaScript error when collapsing any element using Alpine JS x-show) was caused by an error in my app.js file. I had:

    import Alpine from 'alpinejs';
    window.Alpine = Alpine;
    Alpine.start();
    

    None of which is required with Livewire 3, which bundles Alpine JS.

    I have removed it all, and all the errors and duplication of elements have stopped.