-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
Delaying update of height and width in Layout #3180
Conversation
cebb1d2
to
48c95cd
Compare
Codecov Report
@@ Coverage Diff @@
## master #3180 +/- ##
==========================================
- Coverage 36.02% 35.98% -0.05%
==========================================
Files 437 437
Lines 9465 9476 +11
Branches 903 905 +2
==========================================
Hits 3410 3410
- Misses 5460 5470 +10
- Partials 595 596 +1
Continue to review full report at Codecov.
|
@@ -140,14 +140,6 @@ class Layout extends React.Component { | |||
this.onDragEnd = this.onDragEnd.bind(this); | |||
} | |||
|
|||
componentDidMount() { | |||
window.addEventListener('resize', this.onResize); |
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.
are these not needed anymore?
I think we still need to handle the case when the browser window gets resized?
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.
I don’t think so. Because onResize
returns another function the window resize events never actually updates the state.
I will have to double check but I think the SplitPane
onChange
handler fires when browser window is resizes.
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 we need. Try to resize window here https://deploy-preview-3180--storybooks-official.netlify.com
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.
@Hypnosphi I also doubled checked on master
resizing the browser window never triggered onResize
I'm not sure how we should handle browser window resizing since the Layout
onChange
handlers don't fire
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.
I also doubled checked on
master
resizing the browser window never triggeredonResize
Oh I see. Looks like a bug worth fixing to me. Probably caused by onResize
returning a 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.
We should probably extract the part that updates previewPanelDimensions
from onResize
, because it's the only thing that should be done on window resize
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.
Sounds good!. I'll change that in this PR!
height: clientHeight, | ||
}, | ||
}); | ||
}, 50); |
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.
Please use lodash.debounce
package
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.
Or maybe it should rather be lodash.throttle
, see #3180 (comment)
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.
@Hypnosphi Sounds good. I discovered a new issue with using _.throttle
the way that it is currently implemented. it will create a new throttled function on every state update which is bad. Thus I will be changing how the onResize
function and how its passed in to the onChange
handlers
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.
Just apply it in constructor
this.onResize = throttle(this.onResize.bind(this), 200);
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.
I tend to use that method of writing bound class methods a lot.
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.
for readability purposes, it might be better to name it this.onThrottledResize = ...
to differentiate between the two.
I tried it and I can't say I like it:
|
Can we debounce on requestAnimationFrame? |
@wuweiweiw thank you for helping, really appreciate the efforts! I think the immediate feedback of the size is really important, if someone is targetting 800px wide for example, it's annoying to not yet fast feedback, and likely 'overshoot' multiple times.. Do you agree? I think if we can throttle on requestAnimationFrame everything should be optimal right? |
From my understanding of these docs, it seems like this should be used when animating or whenever there's a constraint on browser rendering speed. In this case, I believe the I'm okay with either |
It's only about updating numbers on dimension panel, no need for 60 fps animations |
@Hypnosphi @danielduan @ndelangen done! I rewrote the |
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import SplitPane from 'react-split-pane'; | ||
import _ from 'lodash'; /* eslint-disable-line import/no-extraneous-dependencies */ |
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 use per-function lodash packages. You need to add lodash.throttle
as a dependency to package.json
in lib/ui
, and import it like that:
import throttle from 'lodash.throttle';
By the way, that eslint warning you've suppressed was there for a reason. If you use a package that we don't have as a direct or peer dependency, it will break on user side, because they might not have this dependency
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.
Fixed! :)
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.
Is it? I still see this import and eslint-disable
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.
Oh shoot. I think I accidentally dropped that commit when I was rebasing
Actually, it is created every time, now it's just created directly in |
@Hypnosphi My mistake. But I just got rid of the way And if we put throttle on the inner function returned. It would be executed every time |
The way it was before is more functional-style, the way you do it is more imperative-style. I have no strong feelings about it though |
0b27b6f
to
65329d3
Compare
@Hypnosphi I also added the throttled event handler to window Is there anything else I should do in this PR? |
onResize(pane, mode) { | ||
return size => { | ||
onResize(pane, mode, size) { | ||
if (pane && mode && size) { |
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 hacky to me. Let's extract the part that updates state into a separate function instead.
In fact, the state updates should be throttled (because they provide visual feedback), and the saveSizes
part should be debounced (because it only makes sense to store sizes when they are final)
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.
Sounds good!
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.
@Hypnosphi seems that size
is used to get defaultSize
and that value is only changed when you save it to local storage. Thus I was getting some weird behavior when I was debouncing. So I opted to throttle both.
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.
I also made saveSize on a smaller interval for smoother user experience
@Hypnosphi Fixed! I think we can even get rid of the throttling of |
And also it seems we can call But I think that is out of scope for this PR and I can do it in another :) |
Cool, works like a charm now! |
Issue:
What I did
fixes #1990
Delayed the
setState
call so we don't rerender a billion times.Plus removed adding un-needed event handlers to window
How to test
use React inspector to check state updates
resize the windows and see that the
previewPanelDimensions
state isn't updated thus doesn't rerender until after you stopped dragging for a little bit (50ms)Is this testable with jest or storyshots?
No
Does this need a new example in the kitchen sink apps?
No
Does this need an update to the documentation?
No