【问题标题】:Unmount or re-render screen in drawer navigator在抽屉导航器中卸载或重新渲染屏幕
【发布时间】:2019-08-09 17:47:48
【问题描述】:

我最近刚刚添加了抽屉导航器并将我的屏幕包裹在createDrawerNavigator()

这些是我目前的路线:

  • Home.js
  • Post.js
  • Settings.js

当用户从 Home 导航到 Post 时,我传递了一个包含帖子数据的参数。

onPress={() => this.props.navigation.navigate('Post', {postData: postData})}

当用户从 Post 返回 Home 时,post 将被卸载。并在点击另一个帖子时使用新数据重新加载。

我的问题是,在实现抽屉时,Post 屏幕在导航回 home 时没有被卸载,我一直得到与第一个相同的道具和屏幕帖子打开了,一遍又一遍。

这是我的路线设置:

import React from "react";
import { createDrawerNavigator, createStackNavigator, createAppContainer } from 'react-navigation';
import Home from './screens/Home';
import Post from './screens/Post';
import Settings from './screens/Settings';
import SideBar from './screens/sidebar';

const Drawer = createDrawerNavigator(
{
    Home: {screen: Home},
    Post: {screen: Post},
    Settings: {screen: Settings}
},
{
    initialRouteName: "Home",
    backBehavior: 'initialRoute',
    contentOptions: {
    activeTintColor: "#e91e63"
    },
    contentComponent: props => <SideBar {...props} />,
}
);

const AppNavigator = createStackNavigator(
    {
    Drawer: {screen: Drawer},
    },
    {
    initialRouteName: "Drawer",
        headerMode: "none",
    }
);

export default createAppContainer(AppNavigator);

我做错了什么?

我希望每个帖子屏幕在从主页导航到它时打开并重新呈现为新屏幕。

【问题讨论】:

    标签: react-native react-navigation


    【解决方案1】:

    对于那些使用 react-navigation v5.我遇到了同样的问题,我的组件没有通过使用goBack() 作为抽屉中的屏幕链接来卸载。经过一番研究,我发现在最新版本的 react-navigation 中,他们在抽屉导航器的屏幕选项中添加了一个属性unmountonblur,默认情况下它是 false,这就是组件不卸载的原因。我正在使用它来解决我的问题。

    这是我的代码

    <Drawer.Screen name="ResetLogsStack" component={ResetLogsStack} options={{unmountOnBlur:true}}/>
    

    这里是链接:unmountonblur

    【讨论】:

    【解决方案2】:

    我曾经面临同样的问题。我让我的屏幕Post 监听由react-nativation here 而不是componentDidMount 触发的导航焦点事件。

    import React from 'react';
    import { View } from 'react-native';
    import { NavigationEvents } from 'react-navigation';
    
    const Post = () => (
      <View>
        <NavigationEvents
          onWillFocus={payload => console.log('will focus',payload)}
          onDidFocus={payload => console.log('did focus',payload)} // 
          onWillBlur={payload => console.log('will blur',payload)}
          onDidBlur={payload => console.log('did blur',payload)}
        />
        {/* 
          Your view code
        */}
      </View>
    );
    

    使用onDidFocus,您可以获得导航参数、获取数据和/或更新状态。如果需要,您可以使用onDidBlur 清除屏幕状态。

    或者,您可以使用this doc here 进行命令式编码

    更新:

    顺便问一下,我想知道你为什么把Post 放在抽屉里?难道只是在抽屉里有一个可以访问帖子页面的链接吗?

    在我看来,您应该将HomePost 移动到新堆栈并将Home 作为初始路由。这将确保在导航回Home 后卸载 Post。

    在下面查看我的示例

    const HomeStack = createStackNavigatior({
       Home: {screen: Home},
       Post: {screen: Post},
    }, {
       initialRouteName: 'Home', 
       ...
    })
    
    const Drawer = createDrawerNavigator(
    {
        HomeStack
        Settings: {screen: Settings}
    },
    {
        initialRouteName: "HomeStack",
        backBehavior: 'initialRoute',
        contentOptions: {
           activeTintColor: "#e91e63"
        },
        contentComponent: props => <SideBar {...props} />,
    }
    );
    

    【讨论】:

    • 检查我发布的答案我想我已经解决了,不知道为什么!
    • createDrawerNavigator 中的屏幕以与 Tab 类似的方式安装一次。但是对于 Stack,向后导航会移除(卸载)顶部屏幕
    • 是的,这就是我所做的,我做错了将createDrawerNavigatorcreateStackNavigator 翻转,感谢您澄清它们的工作原理。
    • 有效,我还必须将我在 init useEffect 中的 api 调用移动到 onDidFocus 以防止双重 api 调用。
    • @panchicore:当时,钩子还不存在:D
    【解决方案3】:

    这是react-navigation 的工作方式,为了解决这个问题,您可以添加侦听器,如下所示:

    <NavigationEvents
        onDidFocus={payload => { console.log(payload.state.params,'<- this has your new params') }}
    />
    

     this.props.navigation.addListener('didFocus', payload=>{console.log(payload)})
    

    查看this了解更多信息

    【讨论】:

      【解决方案4】:

      在将 React Navigation 从 2.14.2 更新到 3.11.0 后,我为此浪费了几个小时。有趣的是,它运行良好,升级后页面没有重新渲染,这导致了错误的语言,而不是页面上的实际数据。 我发现的问题是DrawerNavigator screen shouldn't unmount

      所以我们一部分人抱怨它为什么不重新渲染屏幕,一部分人抱怨它为什么重新渲染。第二部分赢得了战斗:)

      基本上解决方案符合预期:监听 WillFocus 事件... 如果您希望在每次访问时重新呈现它,只需将其添加到您的组件的代码中即可。

       /**
       * When using React Navigation Component is not umnounted and instead stored in navigator. 
       * We need component to be rerendered during each visit to show right info and language
       */
      componentDidMount() {
          //this.props.navigation will come in every component which is in navigator
          focusSubscription = this.props.navigation.addListener(
              'willFocus',
              payload => {
                  this.forceUpdate();//Native react function to force rerendering
              }
          );
          this.setState({focusSubscription: focusSubscription});
      }
      
      componentWillUnmount() {
          this.state.focusSubscription.remove();
      }
      

      【讨论】:

        【解决方案5】:

        我尝试使用答案中建议的方法,但它们不适用于我的案例。

        解决方案:

        我尝试用createStackNavigator() 翻转createDrawerNavigator(),它和以前一样完美! 我不必使用反应导航事件,像 componentWillUnmountcomponentWillMount 这样的正常事件可以完美地工作。

        const MainScreens = createStackNavigator(
        {
           Home: {screen: Home},
           Post: {screen: Post},
           Settings: {screen: Settings}
        },
        {
           initialRouteName: "Home",
           headerMode: "none",
        }
        );
        
        const AppNavigator = createDrawerNavigator(
        {
           Main: {screen: MainScreens},
        },
        {
           initialRouteName: "Main",
           backBehavior: 'initialRoute',
           contentOptions: {
           activeTintColor: "#e91e63"
           },
           contentComponent: props => <SideBar {...props} />,
        }
        );
        
        export default createAppContainer(AppNavigator);
        

        不确定我所做的是否有任何问题,但到目前为止它工作正常。

        【讨论】:

          【解决方案6】:

          根据 Muhammad Zain 的回复,如果您使用的是 react navigation v5,您可以直接将选项 unmountOnBlur 传递到抽屉屏幕

          options={{unmountOnBlur:true}}

          这就够了。

          React navigation docs

          【讨论】:

            【解决方案7】:

            我使用 react-navigation 好几个月了。但是将屏幕直接放入抽屉导航器会阻止调用 willunmount 方法。首先将屏幕放置在堆栈导航器中,然后将其放置到抽屉导航器中。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-09-04
              • 1970-01-01
              • 1970-01-01
              • 2020-09-12
              • 2020-02-14
              • 1970-01-01
              相关资源
              最近更新 更多