反应导航:检测屏幕、标签栏何时被激活/出现/聚焦/模糊

react-navigation: Detect when screen, tabbar is activated / appear / focus / blur

以前,当我想在屏幕打开时执行一些操作时,我将它们放在 componentDidMount 中。例如我可以获取一些数据。

像这样。

componentDidMount() {
  this.updateData();
}

但是react-navigation componentDidMount只会在用户第一次打开屏幕时触发一次,如果以后用户再次打开此页面,则不会触发componentDidMount.

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

React 导航 v6

当屏幕聚焦时使用 API 调用获取数据

React Navigation provides a hook that runs an effect when the screen comes into focus and cleans it up when it goes out of focus. This is useful for cases such as adding event listeners, for fetching data with an API call when a screen becomes focused, or any other action that needs to happen once the screen comes into view.

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

function ProfileScreen() {
  useFocusEffect(
    React.useCallback(() => {

      alert('Screen was focused');

      return () => {

        alert('Screen was unfocused');
        // Useful for cleanup functions

      };
    }, [])
  );

  return <View />;
}

表示屏幕是否聚焦的布尔值

React Navigation provides a hook that returns a boolean indicating whether the screen is focused or not. The hook will return true when the screen is focused and false when our component is no longer focused. This enables us to render something conditionally based on whether the user is on the screen or not.

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

function Profile() {
  const isFocused = useIsFocused();

  return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
}

参考 v6.x:https://reactnavigation.org/docs/function-after-focusing-screen/


年长者:

使用 react-navigation,您可以分两步完成:

  1. componentDidMountcomponentWillMount中添加侦听器以挂接事件

  2. 删除 componentWillUnmount 中的侦听器,以避免意外调用

API 参考文档 v3.x, v4.x, v5.x

React 导航 v3.x, v4.x:

addListener - Subscribe to updates to navigation lifecycle

React Navigation emits events to screen components that subscribe to them:

  • willFocus - the screen will focus
  • didFocus - the screen focused (if there was a transition, the transition completed)
  • willBlur - the screen will be unfocused
  • didBlur - the screen unfocused (if there was a transition, the transition completed)

React-navigation 3.x、4.x 示例:

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

// Remove the listener when you are done
didBlurSubscription.remove();

参考 v4.x https://reactnavigation.org/docs/4.x/navigation-prop/#addlistener---subscribe-to-updates-to-navigation-lifecycle

已更新v5.x

活动已更改 v5.x

Screens can add listeners on the navigation prop like in React Navigation. By default, there are 2 events available:

  • focus - This event is emitted when the screen comes into focus
  • blur - This event is emitted when the screen goes out of focus
  • state (advanced) - This event is emitted when the navigator's state changes

示例代码来自 reactnavigation.org

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

  componentWillUnmount() {
    this._unsubscribe();
  }

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

配合挂钩使用

function Profile({ navigation }) {
  React.useEffect(() => {
    const unsubscribe = navigation.addListener('focus', () => {
      // do something
    });

    return unsubscribe;
  }, [navigation]);

  return <ProfileContent />;
}

屏幕上的听众道具

<Tab.Screen
  name="Chat"
  component={Chat}
  listeners={({ navigation, route }) => ({
    tabPress: e => {
      // Prevent default action
      e.preventDefault();

      // Do something with the `navigation` object
      navigation.navigate('AnotherPlace');
    },
  })}
/>

参考 v5.x:https://reactnavigation.org/docs/navigation-events

componentDidMount / componentWillUnmount 并非在所有导航情况下都有效(如选项卡)。

您需要将 addListener 与事件 didFocusdidBlur 一起使用才能执行此类操作。详情见documentation

对于 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);

FOR V5.x 请使用这个。

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

NavigationEvents 是另一种在 JSX 中添加事件监听器的方法。有关详细信息,请参阅 documentation

看起来像这样:

import { NavigationEvents } from 'react-navigation';

return (
  <ScrollView style={styles.container}>
    <NavigationEvents            
      onDidBlur={payload => console.log('did blur', payload)}
    />
    {this.props.children}
  </ScrollView>
);

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} />;
}

react navigation 6中你需要做的就是

import { useIsFocused } from '@react-navigation/native';
function Profile() {
  const isFocused = useIsFocused();

  return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
}

refer docs