Restore the state of a web page rendered in client-side

Hyungsuk Choi
4 min readNov 20, 2020

--

When users traverse history with navigation actions such as backward or forward, it is important to show the user what they were seeing before.

To implement the restore function, if the page is static or is rendered on the server-side, there is no need for any work. But if the page is rendered on the client-side, there are two things to do.

A. Restore the states for querying data. Such as the state of filtering, sorting, index of pagination, and selected tab.

> Whenever states change, store the states in location.search or history.state.

B. Restore the position of the scroll.

> Expand the blank area in advance and replace it when the data comes. By expanding it, you can use the browser’s default scroll restoration.

A. Restore the states for querying data. Such as the state of filtering, sorting, index of pagination, and selected tab.

You can save the state in various places. But I recommend that you save the state in the History, location.search or history.state.

Method A-1. Save in URL’s search.

Like https://www.11st.co.kr/mart/search?categories=1120910&keyword=h&pageIndex=1&sellers=6&sort=pop, you can save the state in window.location.search. Whenever the state are changed, save the state in location.search by using the third argument, url, of the window.history.replaceState API.

I used useEffect for this subscription in the project based on preact.

This method has the advantage of sharing URLs. When a user shares the URL with a friend, the friend can access the page that displays the same data. Also, the bookmark function works well.

And if you use query string, I recommend the CND configuration, Don’t forward query strings to the origin at all. If you don’t forward query strings, CloudFront doesn’t cache based on query string parameters. If not, cache servers will be less efficient.

Method A-2. Save in History.state

If you don’t want to make the URL get messy, save the state in window.history.state by using the first argument, state, of the window.history.replaceState API. I used this method on the main page. Unlike the above search page, the main page doesn’t save each time the state change but saves before unloading the page.

The first argument, state, of the window.history.replaceState API is not like location.search or location.hash. It is a variable of history that can be accessed with history.state. Any serializable value can be saved there.

B. Restore the position of the scroll.

Every browser automatically saves and restores the position of scroll. But the restoration doesn’t work well on the page rendered on the client-side. Because the rendering with fetched data through AJAX has not yet been completed at the time the browser tries restoring.

To resolve this problem, there are 2 solutions. I recommend Solution 2.

Solution 1. Restore manually: You can restore the position of scroll in manually. But I don’t recommend this method because that have 2 drawbacks.

  1. The developer should have additional work that saves the position of scroll.
  2. If you wait until all the data received through ajax is drawn and then move the scroll, users see the horrible scroll jump.

Solution 2. Expand the blank area in advance and replace it when the data comes. By expanding it, you can use the browser’s default scroll restoration: The problem occurs because scroll restoration is run before data comes and is rendered. Therefore, if you expand the area to blank space in advance, the problem can be solved.

I will show you the example.

Example 1. Expanding one area: If there is one area to expand, that is easy. Just expand the area to maximum height.

If the data hasn’t fetched yet, show <SearchResultPadding /> and replace it with <div className=”l_mart”>…</div> or <SearchNoResult /> when the data arrives.

Example 2. Expanding multiple areas with variable height: This is more complicated than the work above. But the principle is the same. If there are 5 areas( A, B, C, D, and E ), expand each of them in advance and replace them when each data come.

In the video above, you can see that the sections expanded with inline style.height are empty. The value of style.height is window.getComputedStyle(section).getPropertyValue(‘height’). I save the values of height into history.state. And restore the data when the user returns to the history entity. When you return and the data exist, sections are rendered like below.

And when a section enters into the viewport, it draws the contents of the section as data and removes the inline style.

The entire code is below.

--

--

Hyungsuk Choi
Hyungsuk Choi

Written by Hyungsuk Choi

Hello. I am a programmer and familiar with Web FE and Node.js.

No responses yet