trevorr / react-scroll-manager

Scroll position manager for React applications
ISC License
36 stars 13 forks source link

Partial success with react 18.2.0 and react-router 6.3.0 #30

Open steinarb opened 1 year ago

steinarb commented 1 year ago

I have an album application https://oldalbum.bang.priv.no/

When navigating up from an album entry, I would like to scroll the album to the entry I'm navigating from.

I have achieved partial success:

  1. Navigation with doesn't position the album on the correct entry
  2. However, if I edit the hash and reload, I am scrolled to the right position

So something works...! :-)

What am I missing to make it work? Or is the problem that the album hasn't been rendered when I try to do the scroll? (is that why editing the URL works?) Or is the problem the router I'm using? (not one of react-router's own, but a router from redux-first-history 5.1.1)

The repo for the application is here: https://github.com/steinarb/oldalbum This is a maven-built java application. The react frontend is here: https://github.com/steinarb/oldalbum/tree/master/oldalbum.web.frontend/src/main/frontend

My experiments with ScrollManager has been pushed to a different repo (I use a dedicated scratch repo to avoid cluttering regular repos with my experiments): https://github.com/steinarb/scratch/commits/oldalbum/router-link-to-anchors

The changes are:

  1. Add an id attribute on the <div> of the album entries
  2. Add an hash matching the id attribute on the up to an album a picture or sub-album is part of
  3. Add a around the (editing the URL and navigating to a hash worked already here)
  4. Add an around each album entry using the id of the div as the scrollKey

Does this sound like something that should work? Or have I misread the docs?

steinarb commented 1 year ago

I've tried inspecting the ScrollManager component to see what's been registered with ScrollManager._registerElement().

But the version of react devtools I have (react devtools 4.27.1 on chromium 108.0.5359.124) does not show any local state on the ScrollManager component.

I haven't used stateful components for a while (I use stateless functional components with redux), so I don't know if it's just this application, or if it's impossible to inspect component local state everywhere currently.

steinarb commented 1 year ago

I disovered that the example in the documentation says <div className="something"> and not <div id="something"> for the first <div> inside the <ElementScroller>.

My problem with that, was that I was already using the className of that <div> for bootstrap styling.

So I first tried wrapping the content of the album entries in an extra <div className={anchor}> but that squashed the layout of the album items horizontally (unsurprisingly actually, since most of the other classes were bootstrap column specifications that now related to this <div>).

So then I tried adding the anchor to the list of classnames. This got me the correct layout back, but scrolling to the album entry I'm navigating back from didn't work here either.

Also: the bit that worked, i.e. editing the hash and pressing enter, stopped working for the above alternatives.

steinarb commented 1 year ago

On reading the documentation I thought that I again had misinterpreted things: <ElementScroller> was meant to surround a component that should be scrolled, and not the item that should be scrolled to.

I.e. in my application: the &ElementScroller> should surround the album (or at least: the part of the album that renders the album entries).

So I removed the <ElementScroller> around the album entries and put an <ElementScroller> around the part of the album that renders the album entries.

But I didn't have any more success: clicking on an up link from a picture to its album, or reloading a window with a hash just navigated to the top of the album.

However, editing the hash to a different value and pressing Enter again worked (I'm thinking this works because I'm bypassing react alltogether and it's just the browser navigating to a specific id in the already rendered DOM...?).

Another thing I tried earlier on that didn't have any visible effect either, was to wrap the entire router content in a <WindowScroller>.