I set up the react-native app with react-native-web. In this app I need to have navigation, so I added react-navigation/native package according to the getting started guide. In mobile platforms everything works well, but in browser navigation doesn’t work as expected. When I just start the app, I can navigate from one page to another without any problem. But when I refresh any page, navigation returns me back to the first Stack.Screen component in Stack.Navigator list. And then, when I click on the Link to another page, nothing happens, no errors appears in console and route doesn’t change.
So the navigation only works properly when I just launch the app and don’t change the route and don’t refresh the page.
Here my linking. I followed the deep linking guide
const linking: LinkingOptions<{
Auth: string;
Home: string;
Table: string;
Loading: string;
}> = {
prefixes: ['alfateacherapp://', 'http://'],
config: {
initialRouteName: 'Loading',
screens: {
Auth: 'auth',
Home: 'home',
Table: 'table',
Loading: 'loading',
},
},
};
Here my NavigationContainer:
<NavigationContainer linking={linking} fallback={<Loading />}>
<Stack.Navigator screenOptions={{ headerShown: false }}>
{isLoadedToken ? (
token ? (
// Screens for logged in users
<Stack.Group>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Table" component={Table} />
</Stack.Group>
) : (
// Auth screens
<Stack.Group>
<Stack.Screen name="Auth" component={Auth} />
</Stack.Group>
)
) : (
<Stack.Screen name="Loading" component={Loading} />
)}
</Stack.Navigator>
</NavigationContainer>
In Home and Table screens I just have the Link from react-navigation/native and Text from react-native.
Home:
<Text>Home</Text>
<Link to={{ screen: 'Table' }}>Link to Table</Link>
Table:
<Text>Table</Text>
<Link to={{ screen: 'Home' }}>Link to Home</Link>
How can I fix this behavior? I need to be able to refresh the page and stay on current route when I’m in browser.
2
Answers
I figured it out! There was some platform-specific code for rendering a web index file. The rootTag displayed the usual react App component when the platform was "web" and AppRegistry from react-native registered the app in all other cases. This was done to bypass the warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead.
When I removed this condition and left only the way that react-native handles the application, everything started working properly.
It’s likely that the URL gets reset after you refresh since you’re rendering the
Loading
screen – React Navigation would adjust the URL to match the currently rendered screen.You should avoid rendering the
NavigationContainer
before you determine whether the user is logged in or not, i.e. theLoading
component shouldn’t be a screen in the stack, but a component that you render directly.The auth flow guide shows a similar approach: https://reactnavigation.org/docs/auth-flow/