【问题标题】:react-navigation: Detect when screen, tabbar is activated / appear / focus / blurreact-navigation:检测屏幕,标签栏何时激活/出现/聚焦/模糊
【发布时间】:2018-10-21 18:46:20
【问题描述】:

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

像这样。

componentDidMount() {
  this.updateData();
}

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

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

【问题讨论】:

    标签: react-native react-hooks react-navigation onfocus viewdidappear


    【解决方案1】:

    在 React 导航 v6 中,您需要做的就是

    import { useIsFocused } from '@react-navigation/native';
    
    function Profile() {
      const isFocused = useIsFocused();
    
      return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
    }
    

    参考 v6.x:https://reactnavigation.org/docs/use-is-focused

    老年人:

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

    1. componentDidMountcomponentWillMount中添加监听器,以钩住事件

    2. 移除componentWillUnmount 中的监听器,避免意外调用

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

    React-navigation 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

    【讨论】:

    • 我这样做。但它只调用一次。当我去另一个应用程序并来到我的应用程序时,我需要再次调用函数。我该怎么办?
    • 从后台打开应用程序不会调用didFocus。你应该使用`AppState.addEventListener('change', this.handleAppStateChange);`。
    • 如何在 5.x 版本中移除监听器?
    • willFocus、didFocus、willBlur 和 didBlur 如何使用 react-navigation v5 实现这一目标?
    • 作为他们的文档,v5.x 有focusblur 事件。对于willdid事件,可以试试state (advanced)
    【解决方案2】:

    适用于 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.     
        });
    }
    

    【讨论】:

    • 没有像你描述的那样工作(对于 v5)。似乎没有任何didFocus 事件。有关详细信息,请参见此处:reactnavigation.org/docs/navigation-events/…。所以stackoverflow.com/a/50290888/1256697 是这里的正确答案。
    • 嗨,这适用于 v3 和 v4,但 v5 正在使用它。 v5 中发生了很多变化,因此您可能想让文档成为您的朋友。 const { navigation } = this.props; this.focusListener = navigation.addListener("focus", () =&gt; { // Call ur function here.. or add logic. });
    • 是的,我知道它是如何工作的(因为我目前正在使用 v5),但我为其他用户添加了评论,以便他们节省一些时间。很好,如果你编辑你的帖子并将它写在里面,你的答案取决于 v3 和 v4
    • @suther 我已经更新了我的答案,感谢您的关注。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      最新版本的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} />;
      }
      

      【讨论】:

        【解决方案5】:

        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 v5。
        【解决方案6】:

        react navigation 6中,您需要做的就是

        import { useIsFocused } from '@react-navigation/native';
        function Profile() {
          const isFocused = useIsFocused();
        
          return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
        }
        

        refer docs

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-17
          • 2021-04-10
          • 2023-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多