一次 React Debug 问题复盘

162 阅读2分钟

背景

phone.png

  1. 上线前 RN 的截图功能,增加了一个需求:要求点击分享时动态生成二维码,然后将二维码截图

    1. 此时截图的二维码是初始化,并不是更新后的
    2. 通过 Image 组件的 onLoad 事件,在图片加载后,再触发截图
  2. 按上述逻辑处理后,产生了一个 Bug:第二次点击分享时,二维码不会更新,页面一直 loading。

    1. 第二次点击时,二维码的 URL 没有更新,所以不会再触发 Image 中 onLoad 事件
    2. 如何触发 onLoad ?
      1. 强制刷新子组件
      2. 通过 timeStamp 每次生成一个新的 QRCode URL

    hooks 原理

    OpportunityURLRef
    didMountu1ref1
    didUpdate(click)u1→u2ref1
    didUpdate(click)u2→u3ref2

    由于我「深刻理解」hooks 原理,明白为什么 Ref 无法获取更新后的二维码:两个 URL 与 Ref 分别在两次 render 中,所以操作当前 Ref 截图,无法获取下次更新的 URL(闭包陷阱)。

    • 保证 Ref 获取最新的 URL,通过 useRef 实现,xxRef 相当于组件中的全局变量(不生效,无法获取最新的二维码 DOM )

    • 使用 Mobx Store 管理 URL,正常的处理不生效,无法获取最新的二维码 DOM;需要通过 setTimeout 延迟执行

      // Before
      await getQRCode(shareTo);
      const uri = await shotRef?.current?.capture();
      const filePath = await uploadIMGFile(uri);
      shareIMGTo(shareTo, filePath);
      
      // After
      await getQRCode(shareTo);
      setTimeout(async () => {
        const uri = await shotRef?.current?.capture();
        const filePath = await uploadIMGFile(uri);
        shareIMGTo(shareTo, filePath);
      }, 800);
      
    • 保证截图的执行时机正确:目前是通过 Image 中 onLoad 事件处理截图逻辑,在 URL 更新后,会触发 onLoad,此时 Ref 能取到最新的 URL

      const onImgLoad = async () => {
        if (qrCodeOnload) { // qrCodeOnload 默认为 false,点击分享时为 true
          const uri = await context?.shotRef?.current?.capture();
          const filePath = await uploadIMGFile(uri);
          setPosterURLMap(Object.assign({}, posterURLMap, { [posterHash]: filePath }));
          shareIMGTo(shareType, filePath);
          setQrCodeOnload(false);
        }
      };
      
  3. 缓存优化:事情到这里并没有结束,产品验收时被 Leader 发现了问题,同一张图,点次下载都会重新请求,明显的等待时间影响用户体验,而且造成资源浪费。如何直接使用之前的资源地址?

前两个问题基本困扰了我8个小时,晚饭也没有吃……第三个问题,让原本一脸懵逼的我,更加茫然,这时我的心态已经崩了,思绪一团乱麻,只想摆烂。

share_logic.png

反思

当时一方面因为晚上要上线,压力很大;然后是因为尝试过几次,觉得这个问题难以解决,比较累,思路也混乱了,做事情没有效率。

  • 需要增强抗压能力;
  • 珍惜每次排查问题的机会,锻炼 Debug 的能力