导航后不调用`componentDidMount()`函数

IT技术 android reactjs react-native stack-navigator
2021-03-27 19:14:37

stackNavigator用于在屏幕之间导航。componentDidMount()在第二个活动中调用了两个 API函数。当我第一次加载它时,它被成功加载。然后我按后退按钮返回第一个活动。然后,如果我再次进入第二个活动,则不会调用 API 并且出现渲染错误。我无法为此找到任何解决方案。任何建议,将不胜感激。

6个回答

如果有人在 2019 年来到这里,试试这个:

import {NavigationEvents} from 'react-navigation';

将组件添加到渲染中:

<NavigationEvents onDidFocus={() => console.log('I am triggered')} />

现在,尽管来自 goBack() 或导航,但每次当页面获得焦点时都会触发这个 onDidFocus 事件。

在哪里使用导航事件?它给了我一个错误“withnavigation 只能用于导航器的视图层次结构”
2021-05-25 19:14:37
没有人为我工作 onDidFocus 和 onWillFocus 。我正在使用 createDrawerNavigator。
2021-06-11 19:14:37
我建议使用 onWillFocus,因为它不会造成任何延迟。焦点是否可能会导致用户可见的轻微延迟。
2021-06-13 19:14:37

如果使用 NavigationEvents 组件的 upvoted 语法不起作用,您可以尝试以下操作:

// no need to import anything more

// define a separate function to get triggered on focus
onFocusFunction = () => {
  // do some stuff on every screen focus
}

// add a focus listener onDidMount
async componentDidMount () {
  this.focusListener = this.props.navigation.addListener('didFocus', () => {
    this.onFocusFunction()
  })
}

// and don't forget to remove the listener
componentWillUnmount () {
  this.focusListener.remove()
}

React-navigation 文档明确描述了这种情况

考虑一个带有屏幕 A 和 B 的堆栈导航器。导航到 A 后,它的 componentDidMount 被调用。当推送 B 时,它的 componentDidMount 也被调用,但 A 仍然挂载在堆栈上,因此它的 componentWillUnmount 不会被调用。

从 B 返回到 A 时,会调用 B 的 componentWillUnmount,但 A 的 componentDidMount 不是因为 A 一直处于挂载状态。

现在有3个解决方案:

订阅生命周期事件

...

React Navigation 向订阅它们的屏幕组件发出事件。有四种不同的事件,你可以订阅: willFocuswillBlurdidFocusdidBlur在 API 参考中阅读更多关于它们的信息。

您的许多用例可能会被withNavigationFocus 高阶组件、<NavigationEvents />组件或 useFocusState钩子覆盖

  1. withNavigationFocus 高阶分量
  2. <NavigationEvents /> 组件
  3. 所述useFocusState钩弃用

withNavigationFocus 高阶分量

import React from 'react';
import { Text } from 'react-native';
import { withNavigationFocus } from 'react-navigation';

class FocusStateLabel extends React.Component {
  render() {
    return <Text>{this.props.isFocused ? 'Focused' : 'Not focused'}</Text>;
  }
}

// withNavigationFocus returns a component that wraps FocusStateLabel and passes
// in the navigation prop
export default withNavigationFocus(FocusStateLabel);

<NavigationEvents /> 零件

import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';

const MyScreen = () => (
  <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>
);

export default MyScreen;

使用FocusState钩子

首先安装库 yarn add react-navigation-hooks

import { useNavigation, useNavigationParam, ... } from 'react-navigation-hooks'

function MyScreen() {   const focusState = useFocusState();   return <Text>{focusState.isFocused ? 'Focused' : 'Not Focused'}</Text>; }

这是我个人的解决方案,仅在从您的 API 获取数据时使用onDidFocus()onWillFocus()呈现:

import React, { PureComponent } from "react";
import { View } from "react-native";
import { NavigationEvents } from "react-navigation";

class MyScreen extends PureComponent {
  state = {
    loading: true
  };

  componentDidMount() {
    this._doApiCall();
  }

  _doApiCall = () => {
    myApiCall().then(() => {
      /* Do whatever you need */
    }).finally(() => this.setState({loading: false}));
  };

  render() {
    return (
      <View>
        <NavigationEvents 
              onDidFocus={this._doApiCall} 
              onWillFocus={() => this.setState({loading: true})}
        />
        {!this.state.loading && /*
        Your view code
        */}
      </View>
    );
  }
}

export default MyScreen;

即使您在屏幕之间导航,React-navigation 也会保持组件安装。您可以使用该组件对这些事件做出react:

<NavigationEvents
  onDidFocus={() => console.log('hello world')}
/>

关于这个组件的更多信息在这里

2020/React Navigation v5 解决方案

在屏幕的 ComponentDidMount 中

componentDidMount() {
    this.props.navigation.addListener('focus', () => {
      console.log('Screen.js focused')
    });
}

https://reactnavigation.org/docs/navigation-events/

或者:将 addListener 方法放在构造函数中以防止重复调用