从其他导航器的另一个屏幕(React Native)返回时,如何刷新屏幕?

时间:2020-09-20 05:23:53

标签: react-native react-navigation navigation-drawer onfocus stack-navigator

我一直在使用StackNavigator来实现我的大多数应用程序。现在,我添加了一个DrawerNavigator,从它的一个屏幕调用原始StackNavigator的另一个屏幕。例如,考虑用户可以执行以下导航顺序:

ScreenA -> ScreenB -> ScreenC

其中ScreenA属于StackNavigator,ScreenB属于DrawerNavigator,而ScreenC再次属于StackNavigator。为此,实际上ScreenA并不直接调用ScreenB,而是另一个屏幕,其唯一目的是充当属于DrawerNavigator的所有屏幕的根。另外,该根在ScreenProps中接收StackNavigator,以便其屏幕以后可以再次使用Stack。

现在,如果我在ScreenC中,并且使用“ this.props.navigation.goBack()”返回,我将返回到ScreenB中的DrawerNavigator,因为这就是所谓的ScreenC。 ScreenB应该刷新其状态,也就是说,它应该从数据库中重新加载信息,因为该信息可能已在ScreenC中更改,因此以前的状态不再有效。

仅在使用StackNavigator时,我总是设法使用“ NavigationEvents”来做到这一点。例如:

import {Component} from 'react'
...
import { NavigationEvents } from 'react-navigation'

class ScreenB extends Component{

    // This is the function that loads information from the database (PouchDB)
    loadInformation = async() =>{
        ...
    }

    render(){
        return(
            <View>
                <NavigationEvents onWillFocus = {payload => this.loadInformation()}/>
                <NavigationEvents onDidFocus  = {payload => this.loadInformation()}/>
                ...
            </View>
        )
    }
}

通过此实现,功能“ loadInformation”在我第一次进入屏幕时以及从子屏幕返回时都被激活。但是这一次我混用了两个导航器,从ScreenC返回到ScreenB时“ onWillFocus”和“ onDidFocus”都没有激活,因此我无法再次进入“ loadInformation”功能。我该怎么办?

编辑:

我还尝试在Redux存储中保留一个布尔变量,该布尔变量确定是否必须激活ScreenB的功能“ loadInformation”。该变量以真实值开头。然后,一旦我进入屏幕B并执行了该功能,它将更改为false。当我导航至ScreenC时,该屏幕中的变量再次更改为true,因此当我返回至ScreenB时,它再次表明必须执行该函数。

需要在ScreenB中使用“ componentDidUpdate”函数,该函数不断检查该变量是true还是false,以便调用“ loadInformation”。那解决了问题,但带来了一个新问题。当我尝试从ScreenB导航到DrawerNavigator的另一个屏幕时,这会花费太多时间,因为在过渡过程中会反复调用“ componentDidUpdate”。因此,该解决方案似乎不可行。

2 个答案:

答案 0 :(得分:0)

很遗憾,您使用的方法<NavigationEvents>已更新。因此,您应该做的是:

class screenA/ screenB/ screenC extends React.Component {
  componentDidMount() {
    this._unsubscribe = navigation.addListener('focus', () => {
      // do something
    });
  }

  componentWillUnmount() {
    this._unsubscribe();
  }

  render() {
    // Content of the component
  }
}

在所有屏幕上使用这些更新的导航事件。希望它能解决您的问题。有关更多信息,See This

答案 1 :(得分:0)

我正在回答我自己的问题。

解决方案是使用 Redux 存储中的布尔变量,指示是否必须激活函数“loadInformation”。假设变量名为“loadView”,默认值为“false”,但 ScreenC 在关闭时将其设置为“true”,因此我们将返回 ScreenB。

也就是说,ScreenC的文件中包含如下代码:

import {Component} from 'react'
import { connect } from 'react-redux'
// Here we import the action that allows to change the value of "loadView"
import { changeLoadView } from '../../redux/actions/popUpActions'
...

class ScreenC extends Component{
    ...
    // Function that is activated automatically when we leave the screen
    componentWillUnmount(){
        // This is the function that assigns the value "true" to "loadView"
        this.props.dispatchChangeLoadView(true)
    }
    ...
}

const mapStateToProps = (state) => {
    return {
        ...
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        dispatchChangeLoadView: (bool) => dispatch(changeLoadView(bool)),
        ....
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(ScreenC);

在 ScreenB 的文件中,我使用了一个“假视图”,它是一个 React 视图,它没有直接放在“渲染”函数中,而是由另一个函数调用(在这种情况下称为“activateLoadInformation”)。该函数返回一个空视图,但使用它的原因是因为在它“返回”之前,我们可以激活我们想要的 ScreenB 的任何其他函数,在这种情况下是“loadInformation”。我不知道另一种激活函数的方法,这些函数在我们想要的时候不会随意渲染任何东西。

import {Component} from 'react'
import { connect } from 'react-redux'
...

class ScreenB extends Component{
    ...
    // This is the function that loads information from the database (PouchDB)
    loadInformation = async() =>{
        this.props.dispatchChangeLoadView(false);
        ...
    }

    // Fake view that calls the function "loadInformation"
    activateLoadInformation(){
        this.loadInformation();
        return(<View/>)
    }

    render(){
        return(
            <View>
                {!this.props.loadView && 
                    <NavigationEvents onWillFocus = {payload => this.loadInformation()}/>
                }
                {this.props.loadView &&
                    this.activateLoadInformation()
                }
                ...
            </View>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        loadView: state.popUpReducer.loadView,
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        dispatchChangeLoadView: (bool) => dispatch(changeLoadView(bool)),
        ....
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(ScreenB);