react-navigation:检测屏幕,tabbar是否激活/出现/聚焦/模糊

ren*_*dom 30 onfocus viewdidappear viewwillappear react-native react-navigation

当我想在屏幕打开时做一些动作时,我把它们放在componentDidMount中.例如,我可以获取一些数据.

像这样.

componentDidMount() {
  this.updateData();
}
Run Code Online (Sandbox Code Playgroud)

但是反应导航componentDidMount只在用户第一次打开屏幕时出现一次,如果以后用户再次打开此页面则不会触发componentDidMount.

检测页面(屏幕)何时被激活并执行操作的正确方法是什么?

tul*_*dev 55

react-navigation,你可以做到这一点.

  1. componentDidMount或中添加侦听器componentWillMount

    this.subs = [
      this.props.navigation.addListener('didFocus', (payload) => this.componentDidFocus(payload)),
    ]; 
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    this.subs = [
      this.props.navigation.addListener('didFocus', this.componentDidFocus),
      this.props.navigation.addListener('willBlur', this.componentWillBlur),
    ];
    
    Run Code Online (Sandbox Code Playgroud)

    然后你可以做任何事情componentDidFocus,比如获取数据,更新数据,......

  2. componentWillUnmount,删除侦听器

    componentWillUnmount() {
      this.subs.forEach(sub => sub.remove());
    }
    
    Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅此PR:https://github.com/react-navigation/react-navigation/pull/3345

更新:

addListener - 订阅导航生命周期的更新

React Navigation将事件发送到筛选订阅它们的组件:

  • willFocus - 屏幕将没有聚焦

  • didFocus - 屏幕将聚焦

  • willBlur - 屏幕聚焦(如果有过渡,则完成过渡)

  • didBlur - 屏幕未聚焦(如果有转换,则转换完成)

参考:https://reactnavigation.org/docs/en/navigation-prop.html#addlistener-subscribe-to-updates-to-navigation-lifecycle

更新示例:

const didBlurSubscription = this.props.navigation.addListener(
  'didBlur',
  payload => {
    console.debug('didBlur', payload);
  }
);

// Remove the listener when you are done
didBlurSubscription.remove();
Run Code Online (Sandbox Code Playgroud)

JSON有效负载:

{
  action: { type: 'Navigation/COMPLETE_TRANSITION', key: 'StackRouterRoot' },
  context: 'id-1518521010538-2:Navigation/COMPLETE_TRANSITION_Root',
  lastState: undefined,
  state: undefined,
  type: 'didBlur',
};
Run Code Online (Sandbox Code Playgroud)

  • 我做这个。但它只调用一次。当我转到另一个应用程序并来到我的应用程序时,我需要再次调用函数。我应该怎么办? (2认同)

Arm*_*mar 12

对于 V3.x 和 V4.x 这可能晚了,但我就是这样解决的。请参阅下面的代码。不要忘记导入 withNavigation 并将导出默认值包装为 withNavigation。

import { withNavigation } from "react-navigation";
 componentDidMount() {
    const { navigation } = this.props;
    this.focusListener = navigation.addListener("didFocus", () => {
      // The screen is focused
      // Call any action
    });
  }

  componentWillUnmount() {
    // Remove the event listener
    this.focusListener.remove();
  }

export default withNavigation(Your Class Name);
Run Code Online (Sandbox Code Playgroud)

FOR V5.x 请使用这个。

 componentDidMount(){
    const { navigation } = this.props;
    this.focusListener = navigation.addListener("focus", () => {      
    // Call ur function here.. or add logic.     
    });
}
Run Code Online (Sandbox Code Playgroud)


zvo*_*ona 6

componentDidMount/ componentWillUnmount不适用于所有导航情况(如标签页)。

您需要使用addListener事件didFocusdidBlur进行此类操作。有关详细信息,请参见文档


Ale*_*dor 5

最新版本react-navigation提供自定义钩子,让您对焦点和模糊事件做出反应:https : //reactnavigation.org/docs/function-after-focusing-screen

以下是他们文档中的一个示例,该示例使用onFocusEffect钩子在焦点上进行 API 调用(它会在屏幕失焦时清除效果):

import { useFocusEffect } from '@react-navigation/native';

function Profile({ userId }) {
  const [user, setUser] = React.useState(null);

  useFocusEffect(
    React.useCallback(() => {
      const unsubscribe = API.subscribe(userId, user => setUser(data));

      return unsubscribe;
    }, [userId])
  );

  return <ProfileContent user={user} />;
}
Run Code Online (Sandbox Code Playgroud)