kee-frame
kee-frame copied to clipboard
"Scroll behavior on navigation" section of the readme seems to be outdated.
Looking at the code the :scroll
option to kee-frame.core/start!
seems to be what matters and requiring kee-frame.scroll
seems to be a no-op because it's already required by kee-frame.router
.
I spent too much of today trying to figure out why a page wasn't scrolling. So I thought I'd write out what's going on under the hood for those who want to know:
Rough outline:
Kee-frame has the :scroll
feature enabled by default.
If you want to disable it, pass :scroll false
to kf/start!
.
When a route changes, kee-frame assumes that you'll fetch some data. It waits until requests have finished and then scrolls the page.
If you don't make a request, then it doesn't scroll the page. I'm not sure if this is a bug or an attempt to stop race conditions. See below for how to fix this.
Specifics
What kee-frame does is (roughly) this:
It uses accountant
to keep track of route changes, once it does it dispatches ::router/route-changed
.
On ::router/route-changed
it:
- Tells
clerk
that the url has changed (but not to scroll, yet) - Updates an
cljs-ajax
interceptor to setup::connection-balance
(which does the:route-counter
stuff below) - Calls
:scroll/poll
after 50 ms
On an ajax request it updates app-db at :route-counter
after which it will contain two things: the route that was just navigated to, and the count of current open requests (basically making sure that all data has been loaded for the page).
On ::scroll/poll
:
- Checks that the route at
:route-counter
is what it expects - Waits until all the requests have completed (the counter is 0)
- Then triggers
::scroll/scroll
which tells clerk to scroll the page
If you don't make any requests
As you can (maybe) see from above, kee-frame assumes that you're going to fetch some data. So if you don't then it won't scroll the page.
Luckily there is a work around, you can put something like this in your code and kee-frame (well, clerk) will wait until your page has finished rendering and then scroll to the top:
(require '[kee-frame.scroll :as scroll]
'[re-frame.core :as rf])
(rf/dispatch [::scroll/scroll])
A PR from someone would be awesome.