Android `componentDidMount()`导航后未调用函数

Android `componentDidMount()`导航后未调用函数,android,reactjs,react-native,stack-navigator,Android,Reactjs,React Native,Stack Navigator,我正在使用stackNavigator在屏幕之间导航。我在第二个活动中调用了componentDidMount()函数中的两个API。当我第一次加载它时,它被成功加载。然后我按下后退按钮返回到第一个活动。然后,如果我再次进入第二个活动,则不会调用API,并且会出现渲染错误。我找不到任何解决办法。如果您有任何建议,我们将不胜感激。在React中,只有在装入组件时才会调用componentDidMount。我想您要做的是在返回StackNavigator时调用API。在父屏幕上调用如下导航时,可以将

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

在React中,只有在装入组件时才会调用componentDidMount。我想您要做的是在返回StackNavigator时调用API。在父屏幕上调用如下导航时,可以将回调函数作为参数传递:

  navigate("Screen", {
     onNavigateBack: this.handleOnNavigateBack
  }); 
  handleOnNavigateBack = () => {//do something};
和在儿童屏幕上

this.props.navigation.state.params.onNavigateBack();
this.props.navigation.goBack();

即使在屏幕之间导航,React navigation也会使组件保持安装状态。您可以使用组件对这些事件作出反应:

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

有关此组件的更多信息。

如果2019年有人来到这里,请尝试以下方法:

import {NavigationEvents} from 'react-navigation';
将组件添加到渲染中:

<NavigationEvents onDidFocus={() => console.log('I am triggered')} />
console.log(“我被触发”)}>

现在,每当页面从goBack()或navigate进入焦点时,都会触发此onDidFocus事件。

每次使用
drawernavigator
stacknavigator
导航到组件后,是否要执行某些操作;为此,
NavigationEvents
componentDidMount
更适合

import {NavigationEvents} from "react-navigation";
<NavigationEvents onDidFocus={()=>alert("Hello, I'm focused!")} />
从“react navigation”导入{NavigationEvents};
警惕(“你好,我很专注!”)}/>

注意:如果您想在每次使用抽屉导航或堆栈导航关注某个组件后执行此任务,则最好使用
导航事件
。但是,如果要执行一次任务,则需要使用
componenetDidMount

如果使用NavigationEvents组件的向上投票的语法不起作用,则可以尝试以下方法:

import {NavigationEvents} from "react-navigation";
<NavigationEvents onDidFocus={()=>alert("Hello, I'm focused!")} />
//无需再导入任何内容
//定义一个单独的函数以在焦点时触发
onFocusFunction=()=>{
//在每个屏幕焦点上做一些事情
}
//在idmount上添加焦点侦听器
异步组件didmount(){
this.focusListener=this.props.navigation.addListener('didFocus',()=>{
this.onFocusFunction()
})
}
//别忘了删除侦听器
组件将卸载(){
this.focusListener.remove()
}

React导航文档:

考虑使用屏幕a和B的堆栈导航器 A、 它的组件称为。按B键时,其 componentDidMount也被称为,但仍在堆栈上装入 因此不调用其组件willunmount

当从B返回到A时,调用componentWillUnmount of B,但是 A的组件安装并不是因为A仍然安装在整体上 时间

现在有3种解决方案:

订阅生命周期事件

React Navigation向订阅的屏幕组件发出事件 他们。您可以订阅四种不同的活动:
willFocus
willBlur
didfours
didflur
。阅读更多关于他们的文章 API参考

您的许多用例可能会被
withNavigationFocus
高阶组件、
组件或
usefocustate
hook

  • 已弃用
  • 带导航焦点
    高阶分量

    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);
    
    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;
    
    以下是我的个人解决方案,使用
    onDidFocus()
    onWillFocus()
    仅在从API获取数据时渲染:

    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;
    
    import React,{PureComponent}来自“React”;
    从“react native”导入{View};
    从“react navigation”导入{NavigationEvents};
    类MyScreen扩展了PureComponent{
    状态={
    加载:正确
    };
    componentDidMount(){
    这个;
    }
    _doApiCall=()=>{
    myApiCall()。然后(()=>{
    /*你需要什么就做什么*/
    }).finally(()=>this.setState({loading:false}));
    };
    render(){
    返回(
    this.setState({loading:true})}
    />
    {!this.state.loading&&/*
    您的视图代码
    */}
    );
    }
    }
    导出默认MyScreen;
    
    根据我们可以使用如下

    componentDidMount(){
    this.unsubscribe=this.props.navigation.addListener('focus',()=>{
    //将在屏幕聚焦时执行
    })
    }
    组件将卸载(){
    这个。取消订阅()
    }
    
    与维托索里索的回答类似,但应根据文件将didFocus改为focus
    //na pagina que você quer voltar
    import {NavigationEvents} from 'react-navigation';
    
    async atualizarEstado() {
      this.props.navigation.setParams({
      number: await AsyncStorage.getItem('count'),
    });}
    
    render() {
    return (
      <View style={styles.container}>
        <NavigationEvents onDidFocus={() => this.atualizarEstado()} />
      </View>
    );
    }
    
    从“react navigation”导入{NavigationEvents}; 异步atualizarEstado(){ this.props.navigation.setParams({ 编号:await AsyncStorage.getItem('count'), });} render(){ 返回( this.atualizarEstado()}/> ); }
    2020/React导航v5解决方案

    在屏幕组件的内部安装

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

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


    我不得不面对这个问题,问题是当你浏览一个页面时,它第一次调用构造函数,componentWillmount,render componentDidmount, 但在第二次导航到同一页时,它只调用render,因此如果您从componentDidmount执行任何API调用或其他操作,它将不会被调用

    而且组件willunmount从未调用过

    您可以使用此方法,如果您将react navigation 5.x与类组件一起使用,它可以解决您的问题。

    对于每个类组件页面,添加此方法并从构造函数调用此方法一次


    componentDidMount
    在其生存期内仅调用一次。请检查
    componentWillReceivePr
    
    useEffect(() => {       
                
        const unsubscribe = props.navigation.addListener('focus', () => {
            // do something
            // Your apiCall();
        });
    
    return unsubscribe;
        
    }, [props.navigation]);
    
    constructor(props) {
        super(props);
        
        this.state = {
            ...
        };
        ...
        this.navigationEventListener(); // call the function
     }
    
    
    
    navigationEventListener = () => { // add this function
            let i = 0;
            const initialState = this.state;
            this.props.navigation.addListener('focus', () => {
                if (i > 0) {
                    this.setState(initialState, () => {
                        //this.UNSAFE_componentWillMount(); // call componentWillMount 
                        this.componentDidMount(); // call componentDidMount
                    });
                }
            });
            this.props.navigation.addListener('blur', () => {
                this.componentWillUnmount();  //call componentWillUnmount
                ++i;
            });
        }