You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让React Navigation的focusHandler仅响应抽屉导航切换?

解决方案

要实现仅在抽屉导航切换时触发firstFunc,而栈内跳转返回不触发,核心是区分焦点来源是抽屉切换还是栈内导航——前者会改变抽屉导航的活跃路由,后者只会改变嵌套栈的状态。

具体实现步骤

  1. 获取抽屉导航实例:由于FirstScreen嵌套在Stack导航中,而Stack又是抽屉的子页面,需要通过两次dangerouslyGetParent()拿到抽屉导航的引用。
  2. 监听抽屉导航的状态变化:当抽屉的活跃路由切换到First且之前不是First时,执行目标函数。
import { useNavigation, useState, useEffect } from '@react-navigation/native';
// 从FirstContext中获取firstFunc
import { useFirstContext } from '../path/to/FirstContext';

function FirstScreen({ navigation }) {
  const { firstFunc } = useFirstContext();
  // 获取当前页面的父级Stack导航
  const stackNav = navigation.dangerouslyGetParent();
  // 获取Stack导航的父级抽屉导航
  const drawerNav = stackNav?.dangerouslyGetParent();
  // 记录上一次抽屉的活跃路由
  const [prevDrawerActiveRoute, setPrevDrawerActiveRoute] = useState(null);

  useEffect(() => {
    if (!drawerNav) return;

    // 初始化时记录当前抽屉的活跃路由
    const initialRoute = drawerNav.getCurrentRoute()?.name;
    setPrevDrawerActiveRoute(initialRoute);

    // 监听抽屉导航的状态变化
    const handleDrawerStateChange = () => {
      const currentActiveRoute = drawerNav.getCurrentRoute()?.name;
      // 仅当抽屉从其他页面切换到First时触发函数
      if (currentActiveRoute === 'First' && prevDrawerActiveRoute !== 'First') {
        firstFunc();
      }
      // 更新上一次的活跃路由记录
      setPrevDrawerActiveRoute(currentActiveRoute);
    };

    const unsubscribe = drawerNav.addListener('state', handleDrawerStateChange);
    // 组件卸载时取消监听
    return unsubscribe;
  }, [drawerNav, firstFunc]);

  // ... 组件其他逻辑
}

关键说明

  • 为什么不用原有的focus监听?因为focus事件会在任何场景下屏幕获得焦点时触发,包括栈内从FirstDetail返回FirstScreen的情况,无法区分来源。
  • 如果需要首次进入First页面时也触发firstFunc,可以调整判断条件为:
    if (currentActiveRoute === 'First' && (prevDrawerActiveRoute !== 'First' || prevDrawerActiveRoute === null)) {
      firstFunc();
    }
    

内容的提问来源于stack exchange,提问作者extradeck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:03:21