kriasoft / universal-router

A simple middleware-style router for isomorphic JavaScript web apps
https://www.kriasoft.com/universal-router/
MIT License
1.7k stars 104 forks source link

Reflecting UI changes to the route #104

Closed ImanMh closed 7 years ago

ImanMh commented 7 years ago

Sometimes this would be grate to have UI state in route. for example in a list that is filtered with some check boxes. When the user clicks on a checkbox I like the route to change so that the user is able to share that route or bookmark it. I don't want to use # since Google will ignore it. currently if I do something like this:

import history from './history';
history.replace('/itemts/filter=discount,new');

It will change the position of my scroll. How can I implement such a thing?

frenzzy commented 7 years ago

The trick is to disable native History API Scroll Restoration behavor and control scroll manually. One of implementation examples you can find here: React-Starter-Kit/src/client.js

ImanMh commented 7 years ago

Yea but sounds like it can never find the pos because current key is not present in the scrollPositionsHistory[location.key]

keys current key

So pos object is never created. What am I doing wrong?

frenzzy commented 7 years ago

If location key does not exist that means the page is opened first time and we usually scroll to top in this case (as for non SPA apps).

ImanMh commented 7 years ago

For me changing line 163 of client.js to this solved scroll jump on history.push or history.replace

      () => onRenderComplete(route, { ...location, key: Object.keys(scrollPositionsHistory).pop() }),

@frenzzy I took a look at client.js and I don't know what I have to change to preserve scroll position during route change. Can you help me out?

frenzzy commented 7 years ago

You need to decide in which case you don't need to scroll. For example you may skip scrolling if path wasn't changed or if history.replace were used.

if (!(previousLocation.pathname === location.pathname && action === 'REPLACE')) {
  window.scrollTo(scrollX, scrollY);
}
ImanMh commented 7 years ago

That should do the job but my question is since scrollPositionsHistory is an object and I don't have previous location(and also it's key), How can I access last position history in scrollPositionsHistory ?

frenzzy commented 7 years ago
let previousLocation = history.location;
function onLocationChange(location) {
  // here you have both location and previousLocation
  previousLocation = location;
}
ImanMh commented 7 years ago

Thanks a lot you are so helpful.