[Fix] preserve sidebar active report highlight between tabs#8227
[Fix] preserve sidebar active report highlight between tabs#8227mdneyazahmad wants to merge 4 commits into
Conversation
PR Reviewer Checklist
|
|
Working on finding any performance related issues |
| // This is usually needed after login/create account and re-launches | ||
| return ( | ||
| <BaseDrawerNavigator | ||
| drawerContent={() => ( |
There was a problem hiding this comment.
Avoid using arrow function callbacks in components that are expensive to re-render. React will re-render this component since each time the parent renders it creates a new instance of that function. Alternative: Bind the method in the constructor instead - https://github.com/Expensify/App/blob/main/PERFORMANCE.md#react-performance-tips
@mdneyazahmad Let's remove the arrow function
There was a problem hiding this comment.
We can not remove it because we have to pass currentlyViewedReportID. The other option is to use Context. May be, we can make SidebarScreen PureComponent.
There was a problem hiding this comment.
I need your help here. What do you think @rushatgabhane ?
There was a problem hiding this comment.
If I'm not wrong, making it a pure component won't help because we have an arrow function.
Anyway, regarding removing the arrow function. It might not make a difference. (I'll verify this once again)
So let's do nothing here
| } | ||
|
|
||
| class ReportScreen extends React.Component { | ||
| class ReportScreen extends React.PureComponent { |
There was a problem hiding this comment.
I wanna know why you've made this a PureComponent.
We should only bother with PureComponent if we're noticing performance problems and have determined the reason of unnecessary re-renders.
Performance.diffObject() in componentDidUpdate() should help you determine this.
ref: https://github.com/Expensify/App/blob/main/PERFORMANCE.md#reconciliation
There was a problem hiding this comment.
https://reactnavigation.org/docs/screen#children
Note: By default, React Navigation applies optimizations to screen components to prevent unnecessary renders. Using a render callback removes those optimizations. So if you use a render callback, you'll need to ensure that you use React.memo or React.PureComponent for your screen components to avoid performance issues.
There was a problem hiding this comment.
@mdneyazahmad I don't find that satisfactory.
Again, we should only bother with PureComponent if we're noticing performance problems and have determined the reason of unnecessary re-renders.
- Does PureComponent reduce number of re-renders? Please provide some kind of verification for this
- PureComponent only does a shallow comparison, so what side-effects (if any) are expected? https://60devs.com/pure-component-in-react.html
There was a problem hiding this comment.
@Beamanator can you please buddy check what I've said above #8227 (comment)
There was a problem hiding this comment.
Agreed @rushatgabhane - The main port of using React.PureComponent would be "to avoid performance issues" right? But if there's no performance gains we don't need to make that change. So please only make this change if we know (if you can prove) there's some benefits 👍
There was a problem hiding this comment.
I will remove PureComponent here.
|
@mdneyazahmad Do we still need |
|
I think, we need Line 207 in b347866 |
| key: ONYXKEYS.NETWORK, | ||
| }, | ||
| currentlyViewedReportID: { | ||
| key: ONYXKEYS.CURRENTLY_VIEWED_REPORTID, |
There was a problem hiding this comment.
Rajat pointed out in 1:1 that currentlyViewedReportID both in Onyx and state is confusing.
@mdneyazahmad when using a single tab, the Onyx key currentlyViewedReportID is in sync with the state.
But when using multiple tabs, this Onyx key has the value of the most recently viewed report.
What do you think of renaming this key to something like mostRecentlyViewedReportID.
There was a problem hiding this comment.
Agree I also figured out this issue when proposing the solution.
There was a problem hiding this comment.
I think renaming currentlyViewedReportID to mostRecentlyViewedReportID in onyx and currentlyViewedReportID is fine in state. What do you think?
There was a problem hiding this comment.
We should be adding "rename" migration anytime we change an Onyx key so the old value transfers to the new key name. But maybe not worth the effort in this case...
There was a problem hiding this comment.
Thanks! TIL about migrations
We'll get it done once the performance issue is addressed.
|
Updated |
|
Sorry for the delay, I'll review this tomorrow. |
marcaaron
left a comment
There was a problem hiding this comment.
Just passing through, but these changes look potentially dangerous as they are changing our lower level navigation code. Can we think of alternatives...?
| <Drawer.Screen | ||
| key={screen.name} | ||
| name={screen.name} | ||
| component={screen.component} |
There was a problem hiding this comment.
Pretty sure this is the recommended practice for rendering a screen component. Why are we changing it?
There was a problem hiding this comment.
In this case we have to pass currentlyViewedReportID across ReportScreen and Sidebar. If we use component={Screen} we can not pass this variables, react-navigation provides one more option for screen component that is to use render props. This way we can pass this state variables to the ReportScreen but this is not the recommended way to pass variables it instead recommends to use Context api for the same. If we use render props we will lose the optimizations applied by the library and we have to manually handle re-rendering of the screen component and also it suggests to use PureComponent in this case.
There was a problem hiding this comment.
source: https://reactnavigation.org/docs/screen/#children
@mdneyazahmad makes sense. Thanks for the context.
There was a problem hiding this comment.
@Beamanator what should we do here? Is it okay to use Context API? That's the closest thing to our previous implementation.
There was a problem hiding this comment.
I'm kinda lost here. Why does this all need to happen at such a low level and why are we duplicating Onyx data in the MainDrawerNavigator state instead of just referencing the value that is stored in Onyx and have the SidebarLinks update when it changes?
There was a problem hiding this comment.
It works without changing this name but lastViewedReportID makes much sense here. User can open multiple reports but it will contain the id of last report opened.
Please do not make this change, thanks!
There was a problem hiding this comment.
I think solution 3 is a good one. It might be needed in the future. Onyx is always the easiest way to manage updates.
There was a problem hiding this comment.
Thanks for the solution 3 and all the help, it is exactly what we need.
@mdneyazahmad let's get it done! :)
(Also, P/S format for the win! Will def use it more)
There was a problem hiding this comment.
We need only this change
Lines 24 to 26 in 43910fe
captureMetrics: Metrics.canCaptureOnyxMetrics(),
+ keysToDisableSyncEvents: [ONYXKEYS.CURRENTLY_VIEWED_REPORTID],I will create a pr to react-native-onyx to add the feature as suggested my @marcaaron
| children: props => ( | ||
| <ReportScreen | ||
| setCurrentlyViewedReportID={this.setCurrentlyViewedReportID} | ||
| /* eslint-disable-next-line react/jsx-props-no-spreading */ | ||
| {...props} | ||
| /> | ||
| ), | ||
| initialParams, | ||
| }, |
There was a problem hiding this comment.
IMO, Really a bad way of doing things. No prop updates should be passed to the Screen components this way. It will create a performance issue.
|
We have decided to close this PR because implementation has changed and this is now handled here #8759 |
Details
When opened multiple report in different tabs, preserve the active report highlighting on sidebar (web only).
Fixed Issues
$ #7792
Tests
PR Review Checklist
Contributor (PR Author) Checklist
### Fixed Issuessection aboveTestssectionQA stepssectionsrc/languages/*filesSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */displayNameproperty(i.e.
StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)PR Reviewer Checklist
### Fixed Issuessection aboveTestssectionQA stepssectionsrc/languages/*filesSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */displayNameproperty(i.e.
StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)QA Steps
Screenshots
Web
web.mp4
Mobile Web
mweb.mp4
Desktop
desktop.mp4
iOS
ios.mp4
Android
android.mp4