#Livewire lazy loading: wait for another component

15 messages · Page 1 of 1 (latest)

light frost
#

I'm struggling with this problem right now in livewire 3 (laravel 10).
On my page I have two livewire components. The second does some Alpinejs stuff when the first livewire component is rendered. Sometimes the seconde component is rendered too fast, so that I get JavaScript issues.
So is there a way that the second component waits for the first one to be done?

blissful meteor
#

Tricky. Could you post your code snippet? I am curious what AlpineJS stuff needs to do after loading.

#

But I did some tinkering, maybe this could help. This is the blade view with 2 Livewire components. ComponentA is the one late to render, while ComponentB is the one executing code depending on the existence of ComponentA.

<livewire:component-b></livewire:component-b>```
Note that I used `lazy` in `<livewire:component-a lazy>` to increase the chance of `componentA` to render after `ComponentB`. I assume you did this too because, as far as I know, if all components do not use lazy loading, all livewire components should(?) render at the same time.

The only way I could think of to inform code living in `componentB` to execute stuff while depending on the existence of `componentA` is by dispatching an event.

This is `componentA`

<div id="component-a" x-data x-init="document.dispatchEvent(new Event('component-a-loaded'))">
Component A
</div>

#

This is componentB

    x-data="{
        doSomething(){ 
            console.log('Component A is Loaded');
            console.log('Did something');
        },
        listeningForComponentALoaded(){
            console.log('Executed by event component-a-loaded');
            this.doSomething();
            this.destroyListener();
        },
        destroyListener(){
            console.log('Helper listeners destroyed');
            document.removeEventListener('component-a-loaded', this.listeningForComponentALoaded);
            document.removeEventListener('livewire:navigating', this.destroyListener);
        },
        init(){
            // If you dabble in React using class components, this will look familiar.
            this.listeningForComponentALoaded = this.listeningForComponentALoaded.bind(this);
            this.destroyListener = this.destroyListener.bind(this);

            // Ensure no dangling listener if user is going away.
            document.addEventListener('livewire:navigating', this.destroyListener);

            if (document.getElementById('component-a')) {
                doSomething();
            } else {
                document.addEventListener('component-a-loaded', this.listeningForComponentALoaded);
            }
        }
    }" 
>
    Component B
</div>```
Honestly, I am not sure that is a good approach. Adding custom events might cause confusion in the future. It's quite troublesome to ensure that the event is removed when it is not needed anymore, to prevent "dangling event listener". But I can't think of something else, I afraid.
light frost
#

Hey JSF, thanks for this detailed answer!

#

Thing is, both components have to lazy load, because both fetch a lot of data from the server with a long response time (sometimes over 30 s).

#

That means, the rest of the site can be rendered, while both components can take their time. While loading, a placeholder is being shown.

#

I, too, thought of using events, but inside the classes of the livewire components, not inside the html markup.

#

Problem is, that event should only occur once. That means, when component A is loaded, only then component B should load.

#

All recurring refreshes of component A shouldn't invoke a refreshing of component B.

#

I know, really messy, but that's what I have to deal with 😦

blissful meteor
#

Oh yeah... $refresh. I had completely forgotten about that.

#

Quite tricky. My solution will no longer fire the component-a-loaded if $refresh is called in componentA. The event listener and handler will not register again in componentB, if $refresh is called in componentB. Well I have ran out of ideas.

light frost
#

Thanks anyway, I appreciate your trying 😉