-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Add public methods for animation #641
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
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`
bvaughn
left a 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.
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._updateScrollLeftForScrollToColumn = this._updateScrollLeftForScrollToColumn.bind(this) | ||
| this._getCalculatedScrollTop = this._getCalculatedScrollTop.bind(this) | ||
| 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
| } | ||
|
|
||
| /** 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 |
bvaughn
left a 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.
This looks good. I like the fact that it's a pretty small footprint. Thanks for making the changes I requested!
| 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:getScrollTopgetScrollLeftscrollToPositionThe
Listcomponent also gets, which passes thru to its ownGrid:getScrollTopscrollToPositionGrid.getScrollTopandGrid.getScrollLeftare 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.scrollToPositionis intended to be used much likeGrid.scrollToRow, so that a component can call it from itsGridinstance 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, orforceUpdatein 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