-
-
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
Add public methods for animation #641
Add public methods for animation #641
Conversation
- Abstracts calculation of `scrollTop` in `Grid._updateScrollTopForScrollToRow` to new method - Also adds public method `List.getScrollTop`
- Abstracts calculation of `scrollLeft` in `Grid._updateScrollLeftForScrollToColumn` to new method
- Calls `Grid._setScrollPosition`, falls back to 0 pixels - Also adds `List.scrollToPosition`
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.
Firstly, thank you for taking the time to contribute this PR and for writing up your thoughts and tests clearly. That's much appreciated! 😁
I'm a little wary of adding more public instance methods for things that could be controlled by props because it adds some maintenance complexity, but I understand why you might want these to avoid having to explicitly un-set properties after an animation completes.
That being said, I have a few requests for changes. Hope that's ok. 😄
source/Grid/Grid.js
Outdated
this._updateScrollTopForScrollToRow = this._updateScrollTopForScrollToRow.bind(this) | ||
this._setScrollPosition = this._setScrollPosition.bind(this) |
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 see why these 3 new functions are bound. They're internal; they're only called from other methods that have the correct context (this
). It doesn't seem like this binding is necessary.
The only reason methods like _onScroll
and _setScrollingContainerRef
are bound this way is that they're passed as properties to React and may not be called with the correct context.
While writing this comment I noticed that _updateScrollLeftForScrollToColumn
and _updateScrollTopForScrollToRow
no longer need to be bound since they aren't passed directly to updateScrollIndexHelper
anymore. 😄
source/Grid/Grid.js
Outdated
*/ | ||
scrollToPosition ({ | ||
scrollLeft = 0, | ||
scrollTop = 0 |
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 scrollLeft
or scrollTop
should have default values of 0. That will make them required parameters. The _setScrollPosition
helper method allows either param to be omitted, in which case the current value in state
won't be modified. This seems convenient if you want to scroll one axis of Grid
without affecting the other.
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 that's a really good point. I was imagining you'd always pass in your x and y here but it's perfectly reasonable to only want to move on one axis.
source/Grid/Grid.js
Outdated
/** | ||
* Gets a calculated value to be used for `scrollLeft` | ||
*/ | ||
getScrollLeft (props = this.props, state = this.state) { |
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.
What's the reason for these 2 methods to accept props
and state
as parameters instead of just using the current values (this.props
and this.state
)? External components really shouldn't know or care about or touch instance.state
. And passing in props
seems like it would make the method more complicated to use.
I was imagining something more like getScrollLeft(columnIndex: number): number
- or maybe even getOffsetForCell({ columnIndex, rowIndex }) => { scrollLeft, scrollTop }
.
Were you trying to allow this method to be called during componentWillReceiveProps
/ componentWillUpdate
with a newer version of props than Grid
currently had? I'm wary of that- in part because of the disconnect between externally-visible props
and internally managed state
.
Edit for clarity: It's okay for methods like _getCalculatedScrollLeft
to accept params for props
and state
since they're private/internal methods. I just don't think we should expose this publicly.
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.
They accept props and state mainly because of laziness and not breaking out the parts I think we actually care about. 😅
The main reason I see this being used for is computing a "target" scrollTop
(or scrollLeft
) based on row or column index. Really, the only things I need to pass are the indexes and the alignment.
getOffsetForCell({ columnIndex, rowIndex, scrollToAlignment }) => { scrollLeft, ScrollTop }
should do the the trick.
source/List/List.js
Outdated
@@ -122,6 +122,11 @@ export default class List extends PureComponent { | |||
}) | |||
} | |||
|
|||
/** See Grid#getScrollTop */ | |||
getScrollTop (props = this.props) { |
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.
Same comment as above RE Grid
^
- Remove unneeded function bindings - Do not default `Grid.scrollToPosition` params to 0 - Add `Grid.getOffsetForCell` and `List.getOffsetForRow` with more specific params
Thanks for taking the time to review my changes @bvaughn! Don't hesitate to let me know if you'd like anything else updated. On this note:
I fully understand this, and the main reason for adding |
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 good. I like the fact that it's a pretty small footprint. Thanks for making the changes I requested!
source/Grid/Grid.jest.js
Outdated
scrollToColumn: 24 | ||
const { scrollLeft, scrollTop } = grid.getOffsetForCell({ | ||
columnIndex: 24, | ||
rowIndex: 49 |
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.
Much nicer 👍
scrollToAlignment = this.props.scrollToAlignment | ||
} = {}) { | ||
const scrollToColumn = columnIndex >= 0 ? columnIndex : this.props.scrollToColumn | ||
const scrollToRow = rowIndex >= 0 ? rowIndex : this.props.scrollToRow |
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.
Tiny nit: You could set the default columnIndex
and rowIndex
values in the same way as you do the scrollToAlignment
for consistency.
I made a couple of small tweaks (eg renamed |
Releasing as 9.7.0 now. Gave you credit in the changelog. Thanks! |
You are welcome! I look forward to seeing what you build with these new methods. Do share! |
This PR adds the following public methods to
Grid
:getScrollTop
getScrollLeft
scrollToPosition
The
List
component also gets, which passes thru to its ownGrid
:getScrollTop
scrollToPosition
Grid.getScrollTop
andGrid.getScrollLeft
are to be used by components that need to know the calculated offsets in pixels for given row and/or column indexes. This is useful for animating.🔗 See the comment in this Plunker for a use case:
Grid.scrollToPosition
is intended to be used much likeGrid.scrollToRow
, so that a component can call it from itsGrid
instance and scroll to a specific offset. This is also useful for animation, so that a component does not have to reset its own internal state after animating, orforceUpdate
in order to force a change in props.Added tests to illustrate how they would work. Commits are atomic. ⚛️
💬 Original conversation in Slack where this came from: https://react-virtualized.slack.com/archives/C1XUJH7HB/p1490898846575686