ReactNative BackHandler简单用法,全局触发,以及物理返回监听不起作用,无法触发

博客探讨了在ReactNative开发中遇到的物理返回键失效和代码冗余问题。作者分析了使用BackHandler的两种方法,并提出了通过屏幕监听事件减少重复代码的解决方案。此外,还发现了NativeBase组件Slide与BackHandler冲突导致的问题,并给出了两种解决办法。文章最后提到了对组件条件渲染和特定属性的使用来避免冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:开发过程中发现

  1. 需要使用物理返回键,但是不起作用
  2. 每个界面都需要添加监听,代码冗余太严重
  3. 有的界面可以返回,有的界面无法返回

涉及第三方库:

        ReactNavigation、 NativeBase。之所以添加这个标题,是因为有个问题与这个包有涉及

BackHandler简单用法

函数组件:两种不同的代码风格,个人比较喜欢第二种风格

  // 方案 一
  const HBPEventListener = () => {
    console.log('ZhaoNanLog: 返回上一界面开始');
    // TODO: 添加导航返回事件
    console.log('ZhaoNanLog: 返回上一界面结束');
  };

  useEffect(() => {
    console.log('ZhaoNanLog: 添加物理返回监听开始');
    BackHandler.addEventListener('hardwareBackPress', HBPEventListener);
    console.log('ZhaoNanLog: 添加物理返回监听结束');
    return () => {
      console.log('ZhaoNanLog: 移除物理返回监听开始');
      BackHandler.removeEventListener('hardwareBackPress', HBPEventListener);
      console.log('ZhaoNanLog: 移除物理返回监听结束');
    };
  }, []);
  // 方案 二
  useEffect(() => {
    console.log('ZhaoNanLog: 添加物理返回监听开始');
    const backListener = BackHandler.addEventListener('hardwareBackPress', () => {
        console.log('ZhaoNanLog: 返回上一界面开始');
        // TODO: 添加导航返回事件
        console.log('ZhaoNanLog: 返回上一界面结束');
    });
    console.log('ZhaoNanLog: 添加物理返回监听结束');
    return () => {
      console.log('ZhaoNanLog: 移除物理返回监听开始');
      backListener.remove();
      console.log('ZhaoNanLog: 移除物理返回监听结束');
    };
  }, []);

类组件

  HBPEventListener() {
    console.log('ZhaoNanLog: 返回上一界面开始');
    // TODO: 添加导航返回事件
    console.log('ZhaoNanLog: 返回上一界面结束');
  };
  componentDidMount() {
    BackHandler.addEventListener('hardwareBackPress', this.HBPEventListener);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.HBPEventListener);
  }

解决代码冗余问题

        本人使用方案二 建议使用方案一

        因为每个界面都需要添加监听,卸载监听,所以有了大量重复的代码。重要的是一个应用有几十个界面,这样带来的工作量非常大。

  方案一:这个问题,做了调查,有的人说,把代码添加到 App.js 入口文件中,这个解决方案还涉及到入口文件中没有导航的问题,需要写一个在没有导航的界面可以使用导航的工具文件。

        参考 ReactNavigation 官网。有个标题叫 Navigating without the navigation prop 根据这篇文章写。

  方案二:这是我自己琢磨出来的,目前没有发现什么问题。但是总觉得第一种方案更加专业高级的样子。

        原理:物理返回事件 BackHandler事件的使用方案就是,在组件挂载后 添加事件监听,当组件将要卸载时移除监听。正是因为这种特殊的方式,所以才会导致代码冗余。

        既然是这样,那么我们是否可以这样理解 在进入界面后,添加事件监听,在退出界面时移除监听

        有什么可以对界面进入退出监听呢?那就是导航,果然,我在官网找到了导航的监听事件。

        问题又回到了远点,我们可以这样进行,那么,导航是否提供一种全局的方法呢?

        还真有, screenListeners 属性,可以将通过他的 props 传入每个界面

        导航提供了四个事件:

  1. state 导航状态变化时触发
  2. focus 界面聚焦时触发
  3. blur 界面失去焦点时触发
  4. beforeRemove 界面将要离开时触发

到这里就很清晰了吧

        将添加物理返回事件的监听添加到 state 或 focus 事件中

        将移除物理返回事件的函数添加到 blur 或 beforeRemove 界面中

  const HBPEventListener = () => {
    console.log('ZhaoNanLog: 返回界面开始');
    // TODO: 添加导航回退的代码
    console.log('ZhaoNanLog: 返回界面结束');
  };

  return (
    <Stack.Navigator
      screenListeners={{
        state: ({data}) => {
            console.log('ZhaoNanLog: 添加物理返回监听');
            BackHandler.addEventListener('hardwareBackPress', HBPEventListener);
        },
        beforeRemove: props => {
            console.log('ZhaoNanLog: 移除物理返回监听');
            BackHandler.removeEventListener(
              'hardwareBackPress',
              HBPEventListener,
            );
        },
      }}>
        .......
        <Stack.Screen >
        .......

    </Stack.Navigator>
 );

部分界面物理返回事件无响应

        过程就不提了,直接说结论

        讲过我大量测试和阅读源码,发现是 NativeBase 中提供的一个组件 与 物理返回事件的监听产生了冲突。我猜测应该是这个样子。

<Slide in={isLoading} placement="top"> ... </Slide> 

这个组件与 BackHandler。 这两个东西肯定是有问题的,只要一起使用,就会出现问题。属性的其他选择我没有测试,至少现在提供的两个参数是会导致物理返回监听不起作用的。

解决方案:

 1.  这个组件就是控制显示的方式的。所以在它需要显示的时候在渲染组件

{ isLoading && <Slide in={isLoading} placement="top"> ... </Slide> } 

2. 使用它的其他属性 overlay=boolean, 这个属性是我阅读源码时发现的,官网文档上没有给,所以也不知道是干什么用的。字面意思就是覆盖的意思,所以

<Slide in={isLoading} placement="top" overlay={isLoading}> ... </Slide> 

在阅读代码时,发现了一个很有意思的问题, 这个组件,应该是 在没有值也就是 undefined 时,应该与 false 走同一个判断,但很奇怪的是,它的效果与 overlay = true 的效果一样。所以我很奇怪。可能在某个地方有赋予默认值,也可能是我阅读的源码并不是该组件的源码。但是这个问题还是解决了,我更倾向于认为,这个在某个地方有赋予的默认值。

这个问题,也没有百度到,似乎,只有我一个人在使用这个组件时遇到了问题。也获取没有人同时使用了这个组件与物理返回事件。总之很开心的是我认真的把这个问题解决了。并找到了解决方案。

        如果有人也遇到了这个问题,并且调查到了原因,麻烦告诉我一声。我很想知道是因为什么导致的这个现象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值