callstack / callstack/react-native-brownfield
popToNative closes all React Native screens
- Lenguaje dominante
- TypeScript
- Estrellas
- 547
- Forks
- 52
- Merge medio
- 3 d 16 h
- PR fusionados (30 d)
- 5
Descripción
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
Guía de contribución
Línea de trabajo
Comienza reproduciendo la demo enlazada y siguiendo la ruta del botón de retroceso que llama a popToNative junto con el SwiftUI NavigationStack y los destinos RNScreen mostrados en el issue. Se considera terminado cuando popToNative cierra únicamente las pantallas de React Native que están en la parte superior del stack, conservando la pantalla nativa y el estado de navegación inferior.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- react-native, swift, typescript
- Área
- mobile-dev
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Tranquilo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 48/100