-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Components: refactorFocalPointPicker
to pass exhaustive-deps
#41520
Conversation
packages/components/src/focal-point-picker/tooltip/index.native.js
Outdated
Show resolved
Hide resolved
packages/components/src/focal-point-picker/tooltip/index.native.js
Outdated
Show resolved
Hide resolved
Size Change: 0 B Total Size: 1.25 MB ℹ️ View Unchanged
|
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.
Code changes LGTM, but I'd definitely wait for someone from the React Native team to check and test changes too (cc @geriux , since you're already part of the reviewers on this PR).
Thank you!
Hey there! I was AFK for a few days, sorry for the delay. I'll check it out 👍 |
@@ -120,7 +120,7 @@ function FocalPointPicker( props ) { | |||
setSliderKey( ( prevState ) => prevState + 1 ); | |||
}, | |||
} ), | |||
[ containerSize ] | |||
[ containerSize, pan, onChange, shouldEnableBottomSheetScroll ] |
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 looks like onChange
is changing on every change that's happening on the Focal point picker when updating the sliders and during the touch events, making the panResponder
to be created constantly.
This prop is coming from here. So I think we should add a useCallback
there (for setPosition
) to prevent this from happening.
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.
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.
Actually scratch that. There's a typo in this commit that was preventing the linter from detecting further issues. Stand by! 😬
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.
Okay, fixed again in 86ba326.
One odd wrinkle is that exhaustive-deps
doesn't seem to mind the empty dep array, when I'd have expected it to want us to add setPosition
as a dependency. If we do add it, we get a warning from the linter (unsurprisingly) that it's changing on every render.
I'm thinking it might be that the linter can detect that setPosition
just calls setDraftFocalPoint
, which in turn comes from useState
and will therefor never change. My understanding is that ESLint is smart enough not to require state-setters as deps, but I didn't realize it could parse through an additional layer of abstraction like this (assuming I'm understanding things correctly 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.
It looks like
onChange
is changing on every change that's happening on the Focal point picker when updating the sliders and during the touch events, making thepanResponder
to be created constantly.
@geriux good catch! How did you come across the changing onChange
value? Did you notice a performance issue or observe it in a different manner? Primarily curious to improve my ability to identify this type of thing in the future.
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.
Thank you for taking the time to dive into this, @chad1008! Also, I appreciate the well-written PR description — great context. 🙇🏻
I tested the proposed changes on an iPhone SE (iOS 15.6) and Samsung Galaxy S20 (Android 12). Aside from the issue I called out for the memoized onChange
, these changes appear to function as expected. 🎉
packages/components/src/mobile/focal-point-settings-panel/index.native.js
Outdated
Show resolved
Hide resolved
@@ -120,7 +120,7 @@ function FocalPointPicker( props ) { | |||
setSliderKey( ( prevState ) => prevState + 1 ); | |||
}, | |||
} ), | |||
[ containerSize ] | |||
[ containerSize, pan, onChange, shouldEnableBottomSheetScroll ] |
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 looks like
onChange
is changing on every change that's happening on the Focal point picker when updating the sliders and during the touch events, making thepanResponder
to be created constantly.
@geriux good catch! How did you come across the changing onChange
value? Did you notice a performance issue or observe it in a different manner? Primarily curious to improve my ability to identify this type of thing in the future.
86ba326
to
5bd332d
Compare
Well spotted @dcalhoun! Thanks for the suggested fix! |
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.
Aside from a small typo I noted and merge conflict resolution, this LGTM. 🚀 Thanks!
…ponder`s `useEffect` dep array
… `startAnimation` in a `useCallback` with relevant deps.
… `useCallback` to prevent excessive re-renders
…x.native.js Co-authored-by: David Calhoun <[email protected]>
0b34818
to
3ebaf4a
Compare
What?
Updates the
FocalPointPicker
component to satisfy theexhaustive-deps
eslint ruleWhy?
Part of the effort in #41166 to apply
exhuastive-deps
to the Components packageHow?
Drag handle
useEffect
Add
pan
to theuseEffect
dep arraypanResponder
locationPageOffsetX
andlocationPageOffsetY
were both declared asuseRef().current
, which is effectivelyundefined
and not an actual ref object.This meant that later on, when mutating these variables, we weren't actually updating a ref, but assigning values that could simply be lost on future renders.
Instead, we now declare both values as actual refs (
useRef()
) and then update the.current
value later on, preserving the assigned value between renders.We then added
pan
,onChange
, andshouldEnableBottomSheetScroll
to theuseEffect
dep array.Tooltip
startAnimation
was expected as a dependency for theuseEffect
call. Doing so also requires wrappingstartAnimation
in its ownuseCallback
, dependent onanimationValue
.Another option on the Tooltip would be to simply move the code executed by
startAnimation
directly intouseEffect
. That function isn't being called anywhere else, so it doesn't really need a separate declaration. This would require addinganimationValue
touseEffect
's dep array.I went with the first option, because while more verbose, I felt the named function improved readability, but I'm happy with either path.
Note:
I've done the best I can with the code changes themselves, but these are all unfortunately React native changes, so I'm a bit out of my depth on actually testing them, so I'm crossing my fingers and calling in the cavalry: cc @geriux.
I'm hopeful these changes and any subsequent adjustments work well 🤞 but if they're too messy I may defer further work on this to a React native expert with better tools/dev environment in place.
Testing Instructions
npx eslint --rule 'react-hooks/exhaustive-deps: warn' packages/components/src/focal-point-picker