-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Hoverable component refactored from class into functional approach #27223
Hoverable component refactored from class into functional approach #27223
Conversation
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
I have read the CLA Document and I hereby sign the CLA |
recheck |
src/components/Hoverable/index.js
Outdated
}); | ||
} | ||
|
||
function Hoverable({disabled, onHoverIn, onHoverOut, children}) { |
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.
Not seeing that you are exporting the Hoverable
component
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.
Done ✅
onMouseEnter, | ||
onMouseLeave, | ||
onBlur, | ||
}); | ||
} | ||
|
||
Hoverable.propTypes = propTypes; | ||
Hoverable.defaultProps = defaultProps; |
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.
Add a displayName field
Hoverable.displayName = 'Hoverable';
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.
AFAIK, there is no need to set displayName
explicitly on components. Should we propose an update to the style doc you've mentioned? Thanks for noticing that!
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.
Yeah, but this standard is from Expensify codebase
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.
Sure, let's keep it this way then :)
src/components/Hoverable/index.js
Outdated
}, [disabled]); | ||
|
||
useEffect(() => { | ||
if (isHovered) return onHoverIn(); |
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 think here is missing the check if (disabled) { return; }
before doing any onHoverXXX
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.
That's a great point! I think we can discuss how flow with disabled
could look like, as it is now conflicting with internal isHovered
state declaration (for example we are not prohibiting event handlers to be executed even if disabled
is set to true
)
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.
Done ✅
src/components/Hoverable/index.js
Outdated
|
||
if (_.isFunction(child.props.onBlur)) child.props.onBlur(el); | ||
}, | ||
[child], |
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.
@gedu, should we list dependency as child
or child.props.onBlur
?
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.
Done ✅
@kacper-mikolajczak check and thick all boxes and add screenshots/videos for all platforms. |
|
||
componentDidMount() { | ||
document.addEventListener('visibilitychange', this.handleVisibilityChange); | ||
document.addEventListener('mouseover', this.checkHover); |
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.
@kacper-mikolajczak It seems this listener has been not migrated, checkHover
is not needed anymore?
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.
Great catch, thanks! Done ✅
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.
@kacper-mikolajczak Overall, the code changes look good. I left some minor comments. Please also complete the checklist. Thanks!
Reviewer Checklist
Screenshots/VideosWebweb.movMobile Web - Chromemweb.chrome.movMobile Web - Safarimweb.safari.movDesktopdesktop.moviOSios.movAndroidandroid.mov |
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.
All good, thanks for PR!
LGTM! |
We did not find an internal engineer to review this PR, trying to assign a random engineer to #16161 as well as to this PR... Please reach out for help on Slack if no one gets assigned! |
Hey folks, I will give a review today 🤞 |
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.
@kacper-mikolajczak Looks good, nice work 🎉 I have a single comment and would be cool if you can get that in or discuss 👍 I tested with updated changes and it works well too.
The reason I brought this change is in react-devtools you'll see the Hoverable
being rendered twice because of isScrolling
and isHovered
.
src/components/Hoverable/index.js
Outdated
this.checkHover = this.checkHover.bind(this); | ||
function InnerHoverable({disabled, onHoverIn, onHoverOut, children, shouldHandleScroll}, outerRef) { | ||
const [isHovered, setIsHovered] = useState(false); | ||
const [isScrolling, setIsScrolling] = useState(false); |
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.
Got you @hurali97! I've implemented suggested changes 👍 Let's review it once again and we are good to go :)
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.
LGTM 🚀
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 for the 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.
Can we just add a comment here since useImperativeHandle
isn't super well known AFAIK?
Then we can LGTM!
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.
LGTM!
Seems jest unit test2 is failing, i'll retry and see if it passes |
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
Regression from this PR: Composer action menu, emoji pickers are broken Screen.Recording.2023-10-02.at.7.09.24.PM.mov |
Regression: This PR seem to have introduced a critical bug where App crashes on pressing back button. @kacper-mikolajczak @ArekChr @Beamanator https://expensify.slack.com/archives/C049HHMV9SM/p1696231998119979 |
Created the GH ticket #28634 |
🚀 Deployed to staging by https://github.com/Beamanator in version: 1.3.76-0 🚀
|
🚀 Deployed to production by https://github.com/mountiny in version: 1.3.76-6 🚀
|
🚀 Deployed to staging by https://github.com/Beamanator in version: 1.3.77-0 🚀
|
🚀 Deployed to production by https://github.com/mountiny in version: 1.3.77-7 🚀
|
Details
In this PR
Hoverable
component was re-written from class to functional approach.Fixed Issues
$ #16161
PROPOSAL: #16161 (comment)
Tests
For platforms with hover:
For platforms without hover:
Offline tests
QA Steps
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Web
Hoverable_web.mov
Mobile Web - Chrome
Hoverable_web_android.mov
Mobile Web - Safari
Hoverable_web_ios.mov
Desktop
Hoverable_desktop.mov
iOS
Hoverable_ios.mov
Android
Hoverable_android.mov