react-nativereact-navigationreact-native-web

Navigation in React Native doesn't work after page refresh


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.


Solution

  • 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.

    AppRegistry.registerComponent('Teacher', () => App);
    
    if (Platform.OS === 'web') {
      const rootTag = createRoot(document.getElementById('root'));
      rootTag.render(<App />);
    } else {
      AppRegistry.runApplication('Teacher', {
        initialProps: {},
        rootTag: document.getElementById('root'),
      });
    }
    

    When I removed this condition and left only the way that react-native handles the application, everything started working properly.

    AppRegistry.registerComponent('Teacher', () => App);
    
    AppRegistry.runApplication('Teacher', {
      initialProps: {},
      rootTag: document.getElementById('root'),
    });