javascript - 在 React Native 中使用 React Navigation 重置嵌套导航路由中的父级

标签 javascript reactjs react-native react-navigation

因此,我使用 React Navigation (v6) 创建了一个导航,如下所示:

  • 首页
  • 工作 - Work.js
    • 工作详细信息 - WorkDetails.js

从“工作概述”屏幕 ( Work.js ) 选择特定工作项后,您将被定向到“Word 详细信息”屏幕以查看更多详细信息。这按预期工作,但是这样做后,按/单击“工作”返回到概述屏幕不再起作用。 “工作详细信息”页面没有任何反应,如果您单击主页并返回,您只需返回到刚刚离开的详细信息特定页面即可。

为了导航到“工作详细信息”屏幕而不将其列在主导航中,我使用了“抽屉”和“堆栈”导航器的组合,如下所示:

App.js

function DrawerMenu() {
  return (
    <Drawer.Navigator 
      useLegacyImplementation 
      screenOptions={{
        headerShown: true, 
        drawerPosition: 'right',
        overlayColor: 'rgba(0,0,0,.5)',              
        drawerActiveTintColor: text,
        drawerInactiveTintColor: text,
        drawerStyle: { backgroundColor: bg, },        
      }}      
      drawerContent={(props) => <CustomDrawerContent {...props} />} >
        <Drawer.Screen name="Home"  component={HomeDrawer}  options={customDrawOptions} />
        <Drawer.Screen name="Work"  component={WorkMenu}    options={customDrawOptions} />
        <Drawer.Screen name="Posts" component={PostsDrawer} options={customDrawOptions} />         
    </Drawer.Navigator>
  );
}

function WorkMenu(){
  return (
    <Stack.Navigator initialRouteName="WorkOverview" 
      useLegacyImplementation
      screenOptions={{
        headerShown: true, 
        drawerPosition: 'right',
        overlayColor: 'rgba(0,0,0,.5)',              
        drawerActiveTintColor: text,
        drawerInactiveTintColor: text,
        drawerStyle: { backgroundColor: bg, },        
      }} >
      <Stack.Screen name="WorkOverview" component={WorkDrawer}       options={{ headerShown: false }} />
      <Stack.Screen name="WorkDetail"   component={WorkDetailDrawer} options={{ headerShown: false }} />
    </Stack.Navigator>  
  );
}

export default function App() {
  return (
    <NativeBaseProvider theme={theme}>
      <NavigationContainer>
        <DrawerMenu />
      </NavigationContainer>
    </NativeBaseProvider>
  );
}

然后从工作概述页面:

Work.js

import { useNavigation } from '@react-navigation/native';

function WorkTile({data}) {
    const navigation = useNavigation(); 
    return ( 
        <Pressable mt={5} shadow="2" rounded="lg" w={{ base: 96, md: 72, lg: 48 }} 
            _light={{ bg: "coolGray.50" }} 
            _dark={{ bg: "gray.800" }} 
            overflow={"hidden"}            
            onPress={() => 
                navigation.navigate("WorkDetail", 
                    { 
                        initial: false, 
                        workDetail: data 
                    }
                )
            }
        >
        ...    
        </Pressable>
    );
}

export default WorkTile;

这只是发送相关的 workDetail: data WorkDetails.js 对象,然后它就会散布在各种 JSX 元素中。

所需的行为类似于它在网络上的 react :
Home -> Work -> Work Details(1) -> Work -> Work Details(2) -> etc.
但它最终的表现如下:
Home <-> Work Details(1)

我尝试添加 initial: false导航到 WorkDetails.js 屏幕时,按照 React Navigation docs以及implementing a reset一旦进入 WorkDetails.js 屏幕,并更新 nested navigation 的配置。 StackOverflow 上的大多数类似问题似乎都是这三种解决方案之一的变体,或者似乎利用自定义按钮/链接(而不是抽屉/标题中自动生成的导航元素)。无论如何,我尝试过的任何方法似乎都无法解决该问题。任何帮助将非常感激。提前致谢!

最佳答案

如果您需要在离开堆栈导航器时重置其导航状态,可以使用 React Navigation 来实现此行为。 v6(即将推出 v7),通过使用 getState setState导航对象的方法,如有关 state persistence 的文档中所述.

但是,为了避免复杂性并保持代码简单,您可以使用 unmountOnBlur screen option 。这是实现所需行为的更直接的方法,因为每次您离开堆栈导航器时,这都会卸载并重置堆栈导航器的状态。

WorkMenu函数将是:

function WorkMenu(){
  return (
    <Stack.Navigator initialRouteName="WorkOverview" 
      useLegacyImplementation
      screenOptions={{
        headerShown: true, 
        drawerPosition: 'right',
        overlayColor: 'rgba(0,0,0,.5)',              
        drawerActiveTintColor: text,
        drawerInactiveTintColor: text,
        drawerStyle: { backgroundColor: bg, },
        // The screen will unmount and its state will be reset when you navigate away
        unmountOnBlur: true,        
      }} >
      <Stack.Screen name="WorkOverview" component={WorkDrawer}       options={{ headerShown: false }} />
      <Stack.Screen name="WorkDetail"   component={WorkDetailDrawer} options={{ headerShown: false }} />
    </Stack.Navigator>  
  );
}

那个unmountOnBlur选项使导航器的行为类似于在网络上的行为,其中离开页面会导致其状态重置。

这应该会给你你正在寻找的行为:Home -> Work -> Work Details(1) -> Work -> Work Details(2) -> etc. .
每次您离开 Work 时堆栈导航器,它将卸载并且其状态将重置,因此导航回 Work总会带你到WorkOverview屏幕。


unmountOnBlur文档确实提到:

Normally, we do not recommend enabling this prop as users do not expect their navigation history to be lost when switching tabs. If you enable this prop, please consider if this will actually provide a better experience for the user.

正确:在某些情况下,使用 unmountOnBlur可能无法提供最佳的用户体验,因为它会清除该堆栈的导航历史记录。但是,根据您希望实现的行为(即,在抽屉中选择“Work”时始终导航回“Work”概述屏幕,无论您进入“WorkDetails”有多深。 '),此方法可以满足您的目的。

如果您想维护“Work”的导航历史记录' 堆栈但在 ' Work 时重置它' 在抽屉中单​​击,另一种方法是创建自定义 DrawerContent组件并处理 onPress对于'Work ' 手动在那里。然后您可以调用navigation.reset对于'Work ' 堆栈,这将实现相同的行为,而不会产生 unmountOnBlur 的副作用。 .

例如:

function CustomDrawerContent(props) {
  const navigation = useNavigation();
  return (
    <DrawerContentScrollView {...props}>
      <DrawerItemList {...props} />
      <DrawerItem
        label="Work"
        onPress={() => {
          navigation.dispatch(
            CommonActions.reset({
              index: 0,
              routes: [
                { name: 'Work', 
                  state: {
                    routes: [
                      { name: 'WorkOverview' },
                    ],
                  }, 
                },
              ],
            })
          );
        }}
      />
      {/* Add other drawer items here */}
    </DrawerContentScrollView>
  );
}

// In your Drawer.Navigator
<Drawer.Navigator drawerContent={(props) => <CustomDrawerContent {...props} />}>
  {/* other screens */}
</Drawer.Navigator>

那个onPress重置 ' Work 的状态' 每次都堆栈到其初始状态 ' Work ' 在抽屉中被点击。这样,'Work当您在其中导航时,堆栈仍将保持其状态,但当您离开并返回时,堆栈将重置。请注意,您必须使用此自定义 onPress仅适用于'Work ' 导航和其他项目应该正常运行。

关于javascript - 在 React Native 中使用 React Navigation 重置嵌套导航路由中的父级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76645679/

相关文章:

reactjs - React 使用静态错误函数将类组件转换为功能组件

javascript - 我如何将 Stripe checkout 与 React 结合使用?

android - React Native - 共享和重用组件

Javascript - 检查 10 个变量是否在 0 和 1 之间的快速方法?

javascript - Swagger 用户界面 : basic auth for swagger file

javascript:将函数的输出更改为指定的小数位

javascript - Node.js JSON 异步解析

javascript - 如何在 React 中循环、返回和渲染对象

ios - React-Native ios 应用程序在我的手机上崩溃

reactjs - 函数后的 Javascript 中的冒号是什么意思?