Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jaspercreel's avatar

Better approach to ignoring stale livewire updates?

I run into this problem a lot. Say I have an input that is a typeahead. User types into it and search results are shown in a div below it. I am debouncing the input already so the update request happens 250ms after the user is done typing.

If the search will take some time on the backend, a second or so, then I can show a loading indicator and wait for the results. No problem there.

The problem comes when a user types into the input, a request is fired off, but then a user types again before the response is received. Now I have two requests fired off. The results box is going to update twice.

I've gotten around this problem in two ways. First, freeze input while the component is awaiting results from a request. This works well in components where more strict input is used, like toggles or checkboxes. However, in a text box this feels cumbersome. Taking away the user's ability to type for up to a second feels bad.

Second, I've sent along a timestamp on every request then stored the most recent request timestamp in alpine. I then dispatch an event from the backend with every result set that contains the timestamp of the request. On the front end, if that event is received and it lines up with the most recent timestamp, I show the results. Otherwise I continue to hide the results behind a loading indicator.

This works better than freezing input in my opinion, but it also feels, I don't know, hacky? Like it feels like Livewire should have an abort method or more elegant way of ignoring updates via the API. I am aware of wire:ignore, but this doesn't seem to fit my problem.

Anyone else encounter this issue and have a more elegant way of solving it?

Thanks!

0 likes
4 replies
LaryAI's avatar
Level 58

To handle the issue of stale updates in Livewire, you can indeed use a more elegant approach without freezing input or relying on timestamps. Here's a solution that leverages Livewire's built-in capabilities and JavaScript to manage concurrent requests more effectively:

Solution: Cancel Previous Requests

  1. Use a Unique Request Identifier: Assign a unique identifier to each request. This can be a simple incrementing number or a UUID. This identifier will help you track which request is the most recent.

  2. Store the Latest Request ID: Keep track of the latest request ID in your Livewire component. This will allow you to determine if a response is outdated.

  3. Check Request ID on Response: When a response is received, compare its request ID with the stored latest request ID. If they match, update the results; otherwise, ignore the response.

Here's how you can implement this:

Explanation:

  • Incrementing Request ID: Each time the updatedSearchTerm method is called, the latestRequestId is incremented. This ensures that each request has a unique identifier.

  • Checking Request Validity: In the performSearch method, before updating the results, it checks if the requestId matches the latestRequestId. If they match, it means this is the most recent request, and the results can be safely updated.

This approach avoids the need to freeze input or use timestamps, providing a clean and efficient way to handle concurrent requests in Livewire.

jaspercreel's avatar

@LaryAI Wouldn't every response from the backend return a stale request id? We are dealing with a situation where the front end has dispatched two network requests to the backend. The backend is in process of returning two responses. Both responses will be self-contained and have their own state, meaning they both believe their request id is the latest. Is that not the case? It seems to be the case in practice.

webrobert's avatar

Interesting. I kinda feel like typehead is more of a rhythm with the user. When I make them I often hate the response and it never quite works how I’d like it. But I’m the one who made it. When I hand it over to the user and I watch them interact with it they find the rhythm and don’t give it a second thought. So I just do a character min and normal debounce. Have you tried out throttle on Livewire 3?

jaspercreel's avatar

@webrobert You are right it is a rhythm game. It feels like I dance, especially since there isn't a "perfect" way to do it.

I don't think throttling would work because I do want to update the typeahead with the latest input from the user, ignoring all previous inputs. A debounce is perfect for this. If I was searching states, a throttle might put me in a situation where a user types in "CO," a search request goes off, then they type an N, making the input "CON". My results are gonna display Colorado and the user is gonna be wondering why "CON" gives them Colorado. If you can't tell, I've tested with this very example, lol.

Unfortunately, while the debounce solves this, it doesn't prevent my results from flashing Colorado for a second before re-rendering with Connecticut. The old request is already out there and I can't abort it. It's like I sent two letters and the response is being sent back for both regardless of whether I want the first one anymore. I can't intercept the mail carrier. I just have to accept it and change my layout twice as a result. This is the weirdness I want to avoid. This is also assuming the requests resolve in order, which might not be the case.

This feels like a problem Livewire should have a solution for but I can't find it in the docs or in other forums, which just seems bizarre? I'm surprised this isn't a more common problem and makes me wonder if I am doing something weird.

For now, my timestamp solution seems to be solving it. But I was hoping someone else had a more elegant solution. I am pretty sure the AI bot is wrong

Please or to participate in this conversation.