在抽屉式导航器中卸载或重新渲染屏幕

时间:2019-03-19 08:57:39

标签: react-native react-navigation

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

这些是我目前的路线:

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

当用户从主页导航到发布时,我传递了一个包含发布数据的参数。

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

只要用户从发布回到首页,发布的邮件就会被卸载。并在点击另一篇文章时再次使用新数据重新安装。

我的问题是,安装抽屉后,导航回 home 时不会卸载 Post 屏幕,我会得到与第一个相同的道具和屏幕帖子一遍又一遍地打开。

这是我的路线设置:

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);

我在做什么错了?

我希望每个帖子屏幕都可以打开,并从首页导航到新屏幕时重新呈现。

7 个答案:

答案 0 :(得分:8)

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

这是我的代码

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

这是该链接:unmountonblur

答案 1 :(得分:1)

我曾经面对同样的问题。我让屏幕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和Drawer放在一起?只是在抽屉中有一个可以访问“帖子”页面的链接?

我认为,您应该将HomePost移至新堆栈,并将Home设置为初始路由。这将确保在导航回到Home后卸载该帖子。

在下面查看我的示例

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} />,
}
);

答案 2 :(得分:1)

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

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

OR

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

检查this以获得更多信息

答案 3 :(得分:0)

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

解决方案:

我尝试用createDrawerNavigator()翻转createStackNavigator(),它的工作原理和以前一样完美! 我不必使用react导航事件,像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);

不确定我所做的事情是否有问题,但到现在为止还可以。

答案 4 :(得分:0)

在将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 :(得分:0)

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

答案 6 :(得分:0)

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

<块引用>

options={{unmountOnBlur:true}}

这就足够了。

React navigation docs