callstack / callstack/react-native-brownfield

popToNative closes all React Native screens

Open
#354 0 comments 1 reaction 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.