Component refactor: migrate PopoverWithMeasuredContent to function component#22868
Component refactor: migrate PopoverWithMeasuredContent to function component#22868luacmartins merged 12 commits intoExpensify:mainfrom
Conversation
| PopoverWithMeasuredContent.displayName = 'PopoverWithMeasuredContent'; | ||
|
|
||
| export default withWindowDimensions(PopoverWithMeasuredContent); | ||
| export default React.memo(PopoverWithMeasuredContent, (prevProps, nextProps) => prevProps.isVisible && !_.isEqual(prevProps, nextProps)); |
There was a problem hiding this comment.
This logic is not correct. Previously this was used with the window dimensions props.
There was a problem hiding this comment.
@s77rt This is not a replace. We change withWindowDimensions to useWindowDimensions hook so hoc is not needed anymore. And we had a shouldComponentUpdate here
App/src/components/PopoverWithMeasuredContent.js
Lines 97 to 105 in e2e4057
React.memo with props comparing function.
There was a problem hiding this comment.
What I meant is the comparison logic is not correct. prevProps.isVisible && !_.isEqual(prevProps, nextProps) this makes no sense and it seems to be the cause of a regression, the floating action button is broken.
There was a problem hiding this comment.
I think I'd better return windowWidth/Height props to handle this update logic - if isVisible update only on dimensions change.
There was a problem hiding this comment.
Let's use the hook and for the React.memo() we can omit the function parameters. The "do not update if only window dimensions change" is useless, the component will pretty much already re-render because we are passing a lot of changing data (e.g. anchorPosition is always a new object).
There was a problem hiding this comment.
No, this leads to a regression with browser window dimensions change. I'll fix the logic
There was a problem hiding this comment.
Interesting bug. We should fix that bug instead of hiding it. Any ideas yet on the root cause?
There was a problem hiding this comment.
@s77rt I think the root cause is that shiftedAnchorPosition left/top could be <0 on some updates. You could see it if you add console.log right before return and leave React.memo without props comparing function. So it seems to be not hiding the bug but prevent unnecessary updates.
There was a problem hiding this comment.
@alexxxwork This still does not explain the root cause. Something is not right, the whole content changes.
Co-authored-by: Carlos Martins <luacmartins@gmail.com>
Co-authored-by: Carlos Martins <luacmartins@gmail.com>
|
@s77rt Last commit fixes a regression in popover position on browser window dimensions change. |
|
@alexxxwork Any update here? (regarding #22868 (comment)) |
|
@s77rt The content changes specifically for context menu, where PopoverWithMeasuredContent is just a wrapping component and it seems to prevent updates that cause content changes in child component - BaseReportActionContextMenu. Content changes because the number of options are determined with the filter here: App/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.js Lines 93 to 103 in 6bcd184 And after some updates this filter shows only two options. This is caused by these props changing for BaseReportActionContextMenu: Props are changing because they are in state in this component App/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.js Lines 306 to 319 in 4a8b431 So I think we should also convert this component to functional to ensure no regressions arise. |
|
The state in PopoverReportActionMenu is cleared by this callback here: |
|
@alexxxwork Can you please explain how is this component effected by others only when it's being a functional component. It's weird. I would expect identical behaviour whether this is written as a functional component or a class component. |
|
@s77rt There's an additional mount/unmount cycle of the component before the context menu opens if we use react.memo without a props comparing function. So when we see the context menu the state variables of the reportID in PopoverReportActionContextMenu is already "0" as if we close the context menu. So when it is updated it changes content. |
|
@alexxxwork Is |
|
@s77rt the additional mount/unmount cycle comes from PopoverWithMeasuredContent - it is called with wrong isContentMeasured value so Popover (and Modal in it) gets unmounted which was unintended by its design. this check should run on every component update Should I add these changes and keep React.memo with props comparing? |
|
@alexxxwork How would changing the dependencies solve this issue? The underlying logic will stay the same. |
|
@s77rt the issue comes from unmounting of child components of PopoverWithMeasuredContent. What dependencies do you mean? |
|
@s77rt please test latest commit |
Reviewer Checklist
Screenshots/Videos |
|
✋ 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/luacmartins in version: 1.3.46-0 🚀
|
|
🚀 Deployed to staging by https://github.com/luacmartins in version: 1.3.47-0 🚀
|
|
🚀 Deployed to production by https://github.com/marcaaron in version: 1.3.46-2 🚀
|
|
🚀 Deployed to production by https://github.com/Beamanator in version: 1.3.47-6 🚀
|






Details
Migrate PopoverWithMeasuredContent to function component
Fixed Issues
$ #16191
PROPOSAL: #16191 (comment)
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)myBool && <MyComponent />.src/languages/*files and using the translation methodWaiting for Copylabel for a copy review on the original GH to get the correct copy.STYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG))Avataris modified, I verified thatAvataris working as expected in all cases)ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Web
Mobile Web - Chrome
Mobile Web - Safari
Desktop
iOS
Android