-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Refactor Hoverable component into functional #29052
Refactor Hoverable component into functional #29052
Conversation
import {DeviceEventEmitter} from 'react-native'; | ||
import {propTypes, defaultProps} from './hoverablePropTypes'; | ||
import * as DeviceCapabilities from '../../libs/DeviceCapabilities'; | ||
import CONST from '../../CONST'; | ||
|
||
function mapChildren(children, callbackParam) { |
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 about adding comments for mapChildren
and assignRef
to clarify why we have this logic.
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.
Thanks for the idea, 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.
Thank you, looks 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.
@kacper-mikolajczak, do we need to extract this logic outside of the component? Usually, if logic is extracted should be moved to utils or helpers dir
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.
@ArekChr Those helpers are not really that universal to move them into utils - I did not want to bloat the component body no more, thus extracted them away. This might help to reduce the cognitive load when studying the component, wdyt?
If not, is there a convention we use for such local helpers? Shall we create a separate file under component's directory called utils
/helpers
?
Thanks for pointing this out!
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 agree that local functions simplify readability. For me, it can stay as it is. But assignRef
seems to be a universal function. It could be moved to, e.g. react utils or helpers. @Beamanator, any thoughts?
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.
Left a few minor comments.
src/components/Hoverable/index.js
Outdated
|
||
const child = useMemo(() => React.Children.only(mapChildren(children, isHovered)), [children, isHovered]); | ||
|
||
const onMouseEnter = useCallback( |
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.
The method should be named for what it does and never what callback they handle, the same for onMouseLeave and onBlur
any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
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 ✅
Reviewer Checklist
Screenshots/VideosWebweb.movMobile Web - Chromemweb.chrome.movMobile Web - Safarimweb.safari.movDesktopdesktop.moviOSios.movAndroidandroid.mov |
src/components/Hoverable/index.js
Outdated
|
||
/** | ||
* Checks the hover state of a component and updates it based on the event target. | ||
* This is necessary to handle cases where the hover state might get stuck due to an unreliable mouseleave trigger, | ||
* such as when an element is removed before the mouseleave event is triggered. | ||
* @param {Event} e - The hover event object. | ||
*/ | ||
checkHover(e) { | ||
if (!this.wrapperView || !this.state.isHovered) { | ||
const unsetHoveredIfOutside = useCallback( |
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 function could be inside useEffect with mouseover listener as it is not used anywhere else
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 ✅
Argggg I was too late reviewing this and now we have conflicts 😅 @kacper-mikolajczak are you able to resolve conflicts tonight / tomorrow? 🙏 Also the manual test steps are a bit sparse, can you please add more test steps for more places this component is used so we are super unlikely to cause any regressions? 🙏 |
Hi @Beamanator no worries! I will resolve conflicts and add the tests you've mentioned tomorrow 👍 |
Thanks very much @kacper-mikolajczak ! 👍 |
Hi @Beamanator! 👋 I've resolved merge conflicts and updated QA steps. Let me know if everything works for you as well! 👍 |
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!
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by https://github.com/Beamanator in version: 1.3.86-0 🚀
|
🚀 Deployed to production by https://github.com/francoisl in version: 1.3.86-5 🚀
|
Details
PR focuses on rewriting the
Hoverable
component from class-based approach to functional one.It builds upon previous PR #27223 and fixes errors reported in the #28634 issue.
Fixed Issues
$ #16161
PROPOSAL: #16161 (comment)
Tests
Offline tests
N/A
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_tests_web.mp4
Mobile Web - Chrome
hoverable_tests_mandroid.mov
Mobile Web - Safari
hoverable_tests_mios.mp4
Desktop
hoverable_tests_desktop.mov
iOS
hoverable_tests_ios.mp4
Android
hoverable_tests_android.mp4