56

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

像这样。

componentDidMount() {
  this.updateData();
}

但是react-navigation componentDidMount当用户第一次打开屏幕时只发生一次,如果以后用户再次打开这个页面,它不会触发componentDidMount。

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

4

6 回答 6

118

反应导航 v6

当屏幕成为焦点时使用 API 调用获取数据

React Navigation 提供了一个钩子,当屏幕聚焦时运行效果并在失焦时清理它。这对于添加事件侦听器、在屏幕成为焦点时通过 API 调用获取数据或屏幕进入视图后需要执行的任何其他操作等情况很有用。

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 提供了一个钩子,它返回一个布尔值,指示屏幕是否聚焦。当屏幕聚焦时,钩子将返回 true,当我们的组件不再聚焦时,钩子将返回 false。这使我们能够根据用户是否在屏幕上来有条件地渲染某些东西。

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. componentDidMount在or中添加侦听componentWillMount器以挂钩事件

  2. 删除监听componentWillUnmount 器,避免意外调用

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

反应导航 v3.x、v4.x

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

React Navigation 向订阅它们的屏幕组件发出事件:

  • willFocus- 屏幕将聚焦
  • didFocus- 屏幕聚焦(如果有过渡,则过渡完成)
  • willBlur- 屏幕将不聚焦
  • didBlur- 屏幕失焦(如果有过渡,则过渡完成)

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 中的事件已更改

屏幕可以像在 React Navigation 中一样在导航道具上添加侦听器。默认情况下,有 2 个事件可用:

  • focus - 当屏幕成为焦点时发出此事件
  • blur - 当屏幕失焦时发出此事件
  • state (advanced) - 当导航器的状态改变时触发此事件

来自 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

于 2018-05-11T11:03:21.427 回答
13

对于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.     
    });
}
于 2019-06-07T09:07:27.970 回答
8

componentDidMount/componentWillUnmount不适用于所有导航情况(如选项卡)。

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

于 2018-05-11T12:31:10.020 回答
6

最新版本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} />;
}
于 2020-05-01T15:36:58.190 回答
4

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

它看起来像这样:

import { NavigationEvents } from 'react-navigation';

return (
  <ScrollView style={styles.container}>
    <NavigationEvents            
      onDidBlur={payload => console.log('did blur', payload)}
    />
    {this.props.children}
  </ScrollView>
);
于 2019-10-17T08:25:58.217 回答
0

反应导航 6中,您需要做的就是

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

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

参考文档

于 2021-10-27T07:40:11.433 回答