callstack / callstack/react-native-brownfield
popToNative closes all React Native screens
- Dominant language
- TypeScript
- Stars
- 547
- Forks
- 52
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 5
Description
Hello,
I've been using react-native-brownfield for a while now and recently we added a new module inside the RNApp project.
A module is a separate stack which comes with its own screens and logic. Normally these modules should be as isolated as possible one from another.
The way I implemented the module is by using the NavigationContainer and the Stack.Navigator from react-navigation.
For testing purposes I've made a new SwiftUI view that allows me to navigate to each module based on the initialModule prop, and from React Native I am passing the prop to NavigationContainer's initialRouteName prop.
Now, just like in the attached video, if I navigate on Home module, then on Settings [native screen], then on Contact [RN screen], and then press the back button [which calls popToNative], it will close all the screens. Basically popToNative closes all the React Native screens.
I am not sure if this is the expected behavior or if it's a bug. I would expect popToNative to close only the React Native screens that are on the top of the stack.
Here is the code I am using:
```swift
import Brownie
import ReactBrownfield
import SwiftUI
import UIKit
enum HomeDestination: Hashable {
case rnHome
case nativeSettings
case rnContact
}
@available(iOS 16.0, *)
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
ZStack(alignment: .topTrailing) {
NavigationStack(path: $path) {
Color(UIColor.systemBackground)
.ignoresSafeArea()
.navigationBarHidden(true)
.navigationDestination(for: HomeDestination.self) { dest in
destinationView(for: dest)
}
}
FloatingHomeButtons { destination in
path.append(destination)
}
.padding(16)
}
}
@ViewBuilder
private func destinationView(for dest: HomeDestination) -> some View {
switch dest {
case .rnHome:
RNScreen(initialModule: "Home")
case .nativeSettings:
SettingsScreen()
case .rnContact:
RNScreen(initialModule: "Contact")
}
}
}
private struct FloatingHomeButtons: View {
let onSelect: (HomeDestination) -> Void
var body: some View {
VStack(alignment: .trailing, spacing: 12) {
Button("Open RN-Home") { onSelect(.rnHome) }
.buttonStyle(.borderedProminent)
Button("Open Native-Settings") { onSelect(.nativeSettings) }
.buttonStyle(.borderedProminent)
Button("Open RN-Contact") { onSelect(.rnContact) }
.buttonStyle(.borderedProminent)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
.allowsHitTesting(true)
}
}
struct RNScreen: View {
let initialModule: String
var body: some View {
ReactNativeView(
moduleName: "RNApp",
initialProperties: [
"nativeOsVersionLabel":
"\(UIDevice.current.systemName) \(UIDevice.current.systemVersion)",
"initialModule": initialModule
]
)
.ignoresSafeArea()
.navigationBarHidden(true)
}
}
@available(iOS 16.0, *)
#Preview {
ContentView()
}
```
```tsx
export default function App({
nativeOsVersionLabel,
initialModule = 'Home',
}: AppProps) {
const initialRouteName: InitialModule =
initialModule === 'Contact' ? 'Contact' : 'Home';
return (
);
}
```
## Reproducible Demo
https://github.com/user-attachments/assets/988917ba-31a1-45a1-8e16-d5513f3f593b
Contributor guide
Assessment
This issue has not been assessed yet.