背景
-
上线前 RN 的截图功能,增加了一个需求:要求点击分享时动态生成二维码,然后将二维码截图
- 此时截图的二维码是初始化,并不是更新后的
- 通过 Image 组件的 onLoad 事件,在图片加载后,再触发截图
-
按上述逻辑处理后,产生了一个 Bug:第二次点击分享时,二维码不会更新,页面一直 loading。
- 第二次点击时,二维码的 URL 没有更新,所以不会再触发 Image 中 onLoad 事件
- 如何触发 onLoad ?
- 强制刷新子组件
- 通过 timeStamp 每次生成一个新的 QRCode URL
hooks 原理
Opportunity URL Ref didMount u1 ref1 didUpdate(click) u1→u2 ref1 didUpdate(click) u2→u3 ref2 由于我「深刻理解」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); } };
-
缓存优化:事情到这里并没有结束,产品验收时被 Leader 发现了问题,同一张图,点次下载都会重新请求,明显的等待时间影响用户体验,而且造成资源浪费。如何直接使用之前的资源地址?
前两个问题基本困扰了我8个小时,晚饭也没有吃……第三个问题,让原本一脸懵逼的我,更加茫然,这时我的心态已经崩了,思绪一团乱麻,只想摆烂。
反思
当时一方面因为晚上要上线,压力很大;然后是因为尝试过几次,觉得这个问题难以解决,比较累,思路也混乱了,做事情没有效率。
- 需要增强抗压能力;
- 珍惜每次排查问题的机会,锻炼 Debug 的能力