How to recover page state in "load more" pagination or infinite scrolling

Hi,

I have “load more” type of pagination in my LiveView app that I implement through phx-update="append". However, when there is a reconnection, the page state is lost – meaning only the initially fetched items are rendered and all the user loaded items are lost.

I have thought of 2 solutions. I was curious if there is a better solution because both these solutions have certain limitations.

Solution 1: Store page count in a hidden form or a data attribute. When there is a reconnection, fetch all items in a single query. A big downside of this approach is that it may increase the DB load depending on the page count.

Solution 2: Implementing infinite scroll pagination (instead of load more) similar to “Discourse” (e.g. ElixirForum), by keeping the page/section state in the URL. However, I think there may always be some parts of the app where a “load more” type of pagination is needed (where you don’t store the page state in the URL).

How would you tackle this problem? (This question also applies to infinite scrolling)

Also related to this, is there a way to efficiently render the previously fetched items when the user uses the browser’s back functionality to go back to the page with “load more” pagination, without reloading all the items from the previous session? This may be within the domain of javascript, but I would love to learn how a javascript solution would play well with a robust live view solution.

Thanks!

2 Likes

I use a “Load More” type pagination with LiveView. I guess a question I would ask you to help put this in context is “if a user wants to send a link to that view to someone else, how would you do it without including the ‘state’ in the URL”? That’s the question I had to ask myself as I was building this. In our app’s industry, most of our competitors have apps that don’t update the URL when things change and it’s frustrating the customer base. I found that by ensuring that every state in our app is accessible by a unique URL, we can satisfy a LOT of prospect complaints in sales calls.

Unfortunately, I have found that the “load more”/infinite scrolling approach is not ideally suited to this due to the amount of data you could potentially need to load (it would have been better to use the more traditional page number style). However, in our real-world use, and because we have included multiple filters and a search box that helps drill down to just the data needed, we aren’t seeing people load a lot of data to find what they need so this is not a problem for us.

I know this is much later than your original post, but I hope it helps a little. :slight_smile:

3 Likes

I agree with your points on the limitations of infinite scrolling & load more with regards to sharing URLs.

I think Discourse (e.g. this forum) does a great job in solving this problem with its own version of bounded infinite scrolling through storing the page state in the URL.

However, my question was about recovering the page state when LiveView reconnects. Like for example, when there is a server restart, the user should be able to stay on the same page section rather than losing the page state (that would feel like an unintentional page refresh for the user).

And maybe, the solution to this problem can also help with restoring the page state when the user uses the back button of the browser to return to the page containing previously loaded items (similar to Twitter’s “back” navigation).

I asked the same question on the slack channel and @stryrckt suggested that this could be solved by combining AlpineJS and Spruce (state management layer for AlpineJS) with push_event. But so far I haven’t had the chance to try it.

You could use connect params to send the state of the page back up, but a simpler solution which also closes the UX gap for infinite scroll is to use push_patch when loading more results, which updates the URL and gives you the recovery mechanism “for free”, but you’ll also need to handle loading previous results in the other direction if you want to restore the current page.

3 Likes

@chrismccord, thanks for sharing your solution.

As far as I understand, what you propose is similar to Discourse’s solution – modify the URL when the user scrolls through the page, right? Probably by handling two events: scroll down triggers load-next and scroll up triggers load-previous.

I was curious if there was a way to restore page state on LiveView reconnects without keeping any state in the URL.

connect params is the way

1 Like

Ok, now I see what you mean by connect params:

let liveSocket = new LiveSocket("/live", Socket, {
  uploaders: Uploaders,
  hooks: Hooks, 
  params: {
    // connect params
    _csrf_token: csrfToken
  }
})

Thanks for pointing out the way to tackle this.