-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improving detection of scroll ended #742
Conversation
…debounce scroll callback will be executed in the expected time.
…mationFrame. setTimout with zero delay was used in Masonry test to wait tasks of requestAnimationFrame finish before assert the result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! I look forward to testing it after work.
source/Grid/Grid.js
Outdated
scrollingResetTimeInterval | ||
) | ||
const delay = () => { | ||
if (Date.now() - this._scrollDebounceStart >= this.props.scrollingResetTimeInterval) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could assign scrollingResetTimeInterval
to a local variable and avoid the this.props.
lookup chain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done.
Hm, looks like there are some conflicts. Try rebasing? |
…debounce scroll callback will be executed in the expected time.
…mationFrame. setTimout with zero delay was used in Masonry test to wait tasks of requestAnimationFrame finish before assert the result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, It's rebased.
source/Grid/Grid.js
Outdated
scrollingResetTimeInterval | ||
) | ||
const delay = () => { | ||
if (Date.now() - this._scrollDebounceStart >= this.props.scrollingResetTimeInterval) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done.
Excellent! Thank you! 😄 I'm going to hold off on merging this until #743 has been merged since that PR is pretty complicated and I don't want to cause any conflicts. Stay tuned! |
source/Grid/Grid.js
Outdated
this._debounceScrollEndedCallback, | ||
scrollingResetTimeInterval | ||
); | ||
const delay = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allocating function on every scroll event can slow down performance.
source/Grid/Grid.js
Outdated
* Check if the difference between current time and the last scroll ended event is greater. | ||
* than the scrollingResetTimeInterval prop, else schedule this function to execute again. | ||
*/ | ||
_delayScrollEnded() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conflict can be solved If you will use class property here instead of bind
_delayScrollEnded = () => {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'm merging right now.
I was just getting a coffee 😄
I did the merge with these last changes on Grid component, but after the merge of this commit, the build is broken:
It is weird because no one warning or error was reported from flow or eslint. What do you think? |
I guess it's https://github.com/brigand/babel-plugin-flow-react-proptypes bug |
Although tests pass, this branch prints a bunch of warnings not present in master:
|
source/Grid/Grid.js
Outdated
_delayScrollEnded = () => { | ||
const { scrollingResetTimeInterval } = this.props; | ||
if (Date.now() - this._scrollDebounceStart >= scrollingResetTimeInterval) { | ||
this._debounceScrollEndedCallback(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nit: I realize we weren't doing this before, and it's no big deal, but we might as well clear this._disablePointerEventsTimeoutId
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree that the pointer must be cleared, but this hasn't been doing on _debounceScrollEndedCallback
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right 😄 Sorry, I was just skimming the diff and that callback wasn't visible. Sorry~ 👍
source/Masonry/Masonry.js
Outdated
const { scrollingResetTimeInterval } = this.props; | ||
if (Date.now() - this._scrollDebounceStart >= scrollingResetTimeInterval) { | ||
this._debounceScrollEndedCallback(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto as for Grid
I'd guess that error is occurring because the following two lines should be |
Nice @jaredLunde, now seems to be ok, the warnings not show up. |
One last place const delay = () => {
if (Date.now() - this._scrollDebounceStart >= this.props.scrollingResetTimeInterval) {
this._debounceScrollEndedCallback()
} else {
this._disablePointerEventsTimeoutId = window.requestAnimationFrame(delay)
}
}
this._scrollDebounceStart = Date.now()
this._disablePointerEventsTimeoutId = window.requestAnimationFrame(delay) So this code snippet is reduced to: this._disablePointerEventsTimeoutId = requestAnimationTimeout(
this._debounceScrollEndedCallback,
this.props.scrollingResetTimeInterval
) And What's going to be the easiest way to review those changes? Does it make more sense to submit a separate PR altogether with this master branch or to submit a PR to @guilhermefloriani's branch? |
Up to you 2 to work out. @guilhermefloriani could give you push access to his fork of RV and you could make your changes directly to it. |
I sent an invite to him. |
… requestAnimationFrame This update also replaces setTimeout/clearTimeout in the WindowScroller component with the requestAnimationFrame-based timeout function.
@@ -1,3 +1,9 @@ | |||
import requestAnimationTimeout, { | |||
cancelAnimationTimeout | |||
} from '../../utils/requestAnimationTimeout' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks a bit weird. Maybe better to use only named exports? And then filename can be changed to animationTimeout.js
} from '../../utils/requestAnimationTimeout' | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To much line breaks
This looks good! I think the only thing remaining would be to fallback to Thanks for your work on this issue! |
This feature has been released in version 9.10.0. Thank you for contributing! |
Oh no, Collection is the one I'm using and experiencing this XD. Any odds there's a fix in the works? |
We are facing some issues like #697 #722 #322 #564 and few others, reporting that there is a problem related to the detection of scroll ended.
Like some people already said in this kind of issue, this is happening because the browser is delaying the
setTimeout
callback on_debounceScrollEnded
in exchange of performance reasons.This is a proposal to fix this kind of problems using
requestAnimationFrame
instead ofsetTimeout
and it works fine for me.This PR includes:
requestAnimationFrame
instead ofsetTimeout
inGrid
component andMasonry
component.requestAnimationFrame
andcancelAnimationFrame
.Masonry
test to wait before all "animations" finish before assert the result. (I did it with asetTimeout
callback becausejest.runOnlyPendingTimers()
does not wait a task scheduled withrequestAnimationFrame
, and this kind of task have priority forsetTimeout
"tasks", so the assert expression will be executed only after_debounceScrollEnded
was called).