-
-
Notifications
You must be signed in to change notification settings - Fork 532
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
fix!: always set Zindex to undefined for InnerScreen #2351
Conversation
65b1b74
to
f4d0502
Compare
Co-authored-by: Kacper Kafara <[email protected]>
f4d0502
to
dd33cdb
Compare
@@ -125,6 +126,7 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>( | |||
<DelayedFreeze freeze={freezeOnBlur && activityState === 0}> | |||
<AnimatedScreen | |||
{...props} | |||
style={[style, { zIndex: undefined }]} |
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'd add a comment that we are handling the order of screens on the native side and changing it here causes issues, with the link to the issue.
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.
+1
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, beside the comment and testing on react-navigation v6 I think we're good. Let me know once the comment is added (mark me for another review).
I've enhanced the PR description, so we can better reconstruct the error mechanism in case its needed in few months.
@@ -125,6 +126,7 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>( | |||
<DelayedFreeze freeze={freezeOnBlur && activityState === 0}> | |||
<AnimatedScreen | |||
{...props} | |||
style={[style, { zIndex: undefined }]} |
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.
+1
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, I think we're good to go. Thank you very much 🎉
…n#2351) ## Description Together with @kkafar we noticed that when switching back between BottomTabsView (A -> B -> A) , React is calling removeScreenAt and addScreen for tab we are leaving - in the same transaction! Because of that and asynchronous nature of react-native-screens, error described in software-mansion#2345 exist. We also noticed that this weir behaviour is related to setting ZIndex in InnerScreen. Fixes software-mansion#2345 Test 2232 was failing due to change in headerBackTitleVisible property. > [!Caution] @kkafar: Note that this change might be potentially breaking since we're effectively removing possibility of managing `Screen` components through "z indices", breaking public API. @kkafar: The error mechanism is as follows: 1. `zIndex` being set causes RN diffing mechanism to include two mutations on the same view in the same transaction - effectively detaching and attaching it, 2. Thus when we navigate from tab B to A, react first detaches B from screen container and in the same transaction it attaches it again - however at the moment of reattach react expects B to be detached. This is not case due to the fact, that we don't execute updates synchronously, but rather we just schedule them in another block on UI thread; 3. React asserts the invariant from point 2., and when we violate it, its internal state gets corrupted later leading to crash. We detected that getting rid of setting `zIndex` on screens prevents the two consecutive operations on the same screen to appear, thus effectively solving the problem. Note, however, that we still won't support such cases with multiple mount/unmount mutations related to the same component in single transaction. ## Changes - For every InnerScreen created we set/override ZIndex style to undefined. - Use headerBackButtonDisplayMode instead of headerBackTitleVisible. ## Test code and steps to reproduce ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: <!-- For adding new props to native-stack --> - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes --------- Co-authored-by: Kacper Kafara <[email protected]>
## Description Together with @kkafar we noticed that when switching back between BottomTabsView (A -> B -> A) , React is calling removeScreenAt and addScreen for tab we are leaving - in the same transaction! Because of that and asynchronous nature of react-native-screens, error described in #2345 exist. We also noticed that this weir behaviour is related to setting ZIndex in InnerScreen. Fixes #2345 Test 2232 was failing due to change in headerBackTitleVisible property. > [!Caution] @kkafar: Note that this change might be potentially breaking since we're effectively removing possibility of managing `Screen` components through "z indices", breaking public API. @kkafar: The error mechanism is as follows: 1. `zIndex` being set causes RN diffing mechanism to include two mutations on the same view in the same transaction - effectively detaching and attaching it, 2. Thus when we navigate from tab B to A, react first detaches B from screen container and in the same transaction it attaches it again - however at the moment of reattach react expects B to be detached. This is not case due to the fact, that we don't execute updates synchronously, but rather we just schedule them in another block on UI thread; 3. React asserts the invariant from point 2., and when we violate it, its internal state gets corrupted later leading to crash. We detected that getting rid of setting `zIndex` on screens prevents the two consecutive operations on the same screen to appear, thus effectively solving the problem. Note, however, that we still won't support such cases with multiple mount/unmount mutations related to the same component in single transaction. ## Changes - For every InnerScreen created we set/override ZIndex style to undefined. - Use headerBackButtonDisplayMode instead of headerBackTitleVisible. ## Test code and steps to reproduce ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: <!-- For adding new props to native-stack --> - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes --------- Co-authored-by: Kacper Kafara <[email protected]> (cherry picked from commit 53695c3)
Description
Together with @kkafar we noticed that when switching back between BottomTabsView (A -> B -> A) , React is calling removeScreenAt and addScreen for tab we are leaving - in the same transaction! Because of that and asynchronous nature of react-native-screens, error described in #2345 exist. We also noticed that this weir behaviour is related to setting ZIndex in InnerScreen.
Fixes #2345
Test 2232 was failing due to change in headerBackTitleVisible property.
Caution
@kkafar:
Note that this change might be potentially breaking since we're effectively removing possibility of managing
Screen
components through "z indices", breaking public API.@kkafar:
The error mechanism is as follows:
zIndex
being set causes RN diffing mechanism to include two mutations on the same view in the same transaction - effectively detaching and attaching it,We detected that getting rid of setting
zIndex
on screens prevents the two consecutive operations on the same screen to appear, thus effectively solving the problem.Note, however, that we still won't support such cases with multiple mount/unmount mutations related to the same component in single transaction.
Changes
Test code and steps to reproduce
Checklist