ReactNative componentDidMount没有被调用

时间:2018-10-24 20:38:50

标签: react-native react-navigation

我有两个屏幕:A和B,与StackNavigator连接

屏幕A是QR码扫描仪。扫描QR码后,它立即导航到屏幕B。

在屏幕B中,我使用从屏幕A作为导航参数传递的QR码进行API调用。我在componentDidMount中触发了此API调用。

我的问题是:如果我从A导航到B,然后返回A,然后再次导航到B,则不会调用componentDidMount,并且我无法触发API调用。


编辑:

这是一些代码

屏幕A

在扫描QR码时调用的处理程序函数:

handleQRCode = qrCode => {
    NavigationService.navigate('Decode', {qrCode});
};

屏幕B

QR代码从导航状态参数中提取,并通过redux用于API调用(startDecode)。

componentDidMount() {
    qrCode = this.props.navigation.state.params.qrCode;
    this.props.startDecode(qrCode.data);
}

我的问题是,componentDidMount仅在首次采用该路由时才被调用。

3 个答案:

答案 0 :(得分:1)

react-navigation中,每个屏幕都保持安装状态。这意味着当您返回到B时,您可能已经更改了道具,但是componentDidMount在此屏幕的首次创建中已经被调用。

有两种可供选择的选项(AFAIK)可以处理这种情况:

  1. 您可以使用以下方法来代替致电this.props.navigation.navigate() this.props.navigation.push将创建另一个实例 屏幕B,从而调用componentDidMount React生命周期 事件。
  2. 在屏幕B中,您可以捕获道具更改的事件。 这可以发生在新的静态生命周期事件中 getDerivedPropsFromState,也可以在不久的将来完成 不推荐使用的componentWillReceiveProps

答案 1 :(得分:1)

我遇到了类似的问题,因此我使用this.props.navigation.addListener()来解决它。基本上,可以通过再次推动相同的屏幕using a key(我还没有尝试过)来强制调用componentDidMount()(但您的堆栈也将保持增长,这不是最佳选择)。因此,当您返回到已经在堆栈中的屏幕时,可以使用addListener()来查看它是否重新聚焦,并且可以在此处复制componentDidMount()代码:

class MyClass extends Component {

  someProcess = () => {
    // Code common between componentDidMount() and willFocus()
  }

  componentDidMount() {
    this.someProcess();
  }

  willFocus = this.props.navigation.addListener(
    'willFocus',
    (payload) => {
      this.someProcess();
    }
  );

}

第一次调用MyClass时,将调用componentDidMount。在其他时候它仍然处于堆栈中但只是获得焦点时,将addListener被调用。

答案 2 :(得分:0)

之所以发生这种情况,是因为B组件仅在首次访问时才安装,因此不会再次调用componentDidMount。

我建议您通过'didAppear'事件将回调传递给导航器的setOnNavigatorEvent方法。您的回调将在react-native-navigation发出的每个事件上调用,并且您可以验证每次屏幕出现时都执行逻辑(因此使用'didAppear'事件)。您可以基于以下代码:

export default class ExampleScreen extends Component {
  constructor(props) {
    super(props);
    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
  }

  onNavigatorEvent(event) {
    if (event.id === 'didAppear') {
      // do API call here
    }
  }
}