reach / router

Home Page:https://reach.tech/router

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Discussion: use `replaceState` for mutating `location.state`

czabaj opened this issue · comments

Imagine you have data that you want to persist to a particular location in history, e.g. expanded items on the listing, which shall be remembered when the user navigates to the detail and then returns back (with propper history.back or navigate (-1) or similar).

I thought it would be best to store such location specific data into the History API state and mutate them via

navigate(currentLocation, {
  replace: true,
  state: { ...currentLocation.state, [myDataKey]: myData }
})

This has two very convenient properties

  • in contrast to Web Storage API like sessionStorage it supports JavaScript objects so we don't need de/serialization for the data,
  • the change of location will be propagated to all location listeners, so this supports reactivity, which sessionStorage does not.

But this has also one (and maybe not only one) very nasty property, which blocks usage of this approach

  • with every location change, reach/router triggers focus of the main area, which could have many side effects, e.g. in my app it scrolls the page to the top of the main content upon every storage via this mechanism.

Given the benefits this technique has, I'm thinking whether it deserves some more investigation. I could, for example, disable focus when there is a replace call with no change in the path. But this might have other side effects. which I'm not aware of right now, which disqualifies this technique. Interestingly, scroll restoration in Gatsby uses sessionStorage, whilst History API state feels to be a perfect fit for such use-case.

Can please someone with a better understanding of HIstory API provide more insights into whether using replaceState is good or bad for mutating the state of the current location?

I'm reviving this thread. The History API replaceState seems to be specifically prepared for mutating the state object, thus the re-focus caused by @reach/router feels like a bug - it shall not focus the main content when there is only change in a state object. Correct?