react-nativeexporeact-navigationexpo-router

Expo Router - preserve state of screen when pushing a new one


I'm working with Expo Router in React Native. I'm noticing that when I use router.back() the previous screen is not keeping it's old state, it just re-renders.

Example:

export default ScreenA = () => {

  useEffect(() => {
    // This is executed again when going back.
  }, [])

  return <Link href="screen-b">Screen B</Link>

}

export default ScreenB = () => {

  const router = useRouter();
  return <Pressable onPress={() => router.back()}>Screen A</Pressable>

}

Is there any solution to this? I've thought about moving some parts of the state to redux, but is there anything simpler? Should I move to React Navigation?


Solution

  • Please look at my comment in the github issue here: https://github.com/expo/router/issues/460#issuecomment-1973959243

    I think the solution is: In your _layout, replace the Slot with Tabs like below.

    import { Link, Slot, Stack } from 'expo-router'
    import { Tabs } from 'expo-router/tabs'
    
                      {/* <Slot /> */}
                      {/* <Stack screenOptions={{ headerShown: false }} /> */}
                     <Tabs
                        screenOptions={({ route }) => ({
                          headerShown: false,
                          tabBarStyle: {
                            // display: route.name === 'example' ? 'none' : 'flex',
                            display: 'none',
                          },
                        })}
                      />
    

    The result will be similar to using Tab Navigation of the react-navigation. In Tab Navigation it displays the route again (if mouted previously) without reloading/rerendering it. It will use the previously rendered version of that route.

    Comparing the different route rendering methods: