React Native 开发环境请求两次:别急着关掉 Strict Mode
·
专题:Hooks 与状态

开发时刚打开页面,服务端就收到两次读取请求;发布包却只出现一次。很多人会直接移除 Strict Mode,表面安静了,但订阅泄漏、异步竞态和清理缺失也一起被藏了起来。
先理解问题
Strict Mode 会在开发环境对 Effect 增加一次设置和清理检查。工程需要满足的是:前一轮失效后不能继续改变当前界面,资源应被释放。取消请求可以节约资源,但不能保证请求尚未到达服务端,也不能代替服务端对写操作的幂等处理。
实现路径
- 记录 setup、cleanup 和请求编号,先确认双请求来自 Effect 检查,而非按钮绑定两次。
- 让每轮 Effect 拥有自己的有效标记,清理时失效;读取接口可根据环境能力额外取消。
- 把创建订单、支付确认这类用户动作放在事件流程,并使用稳定业务请求身份,不要绑定到“页面刚挂载”。
核心示例
import {useEffect, useState} from 'react';
export function useLabel(load: () => Promise<string>) {
const [label, setLabel] = useState('');
useEffect(() => {
let active = true;
load().then(value => {
if (active) setLabel(value);
}).catch(() => {
if (active) setLabel('加载失败');
});
return () => { active = false; };
}, [load]);
return label;
}
这里的 load 是由调用方传入的稳定函数;如果每次渲染都新建它,会正常触发重新同步。active 属于单次 Effect,不会误把上一轮结果当成本轮结果。它保护的是界面提交,不会让已经发出的网络包消失。
容易忽略的边界
用一个“已经执行过”的 ref 阻止第二次 setup,可能同时阻止真正需要的重新连接。更危险的是第一次 setup 已被 cleanup 释放,第二次又被跳过,页面便留下一个看似初始化过、实际上没有资源的状态。
怎么验证
- 人为延迟第一轮响应:最后界面应来自仍有效的一轮。
- 返回页面后重新进入:订阅能正常建立,而不是被永久跳过。
- 对比开发与发布日志:解释差异,但不要以次数相同作为唯一成功条件。
保留这次开发期压力检查,把清理写完整,通常比隐藏一次额外请求更有长期价值。
适用范围与参考
示例用于说明设计与排查方法,非完整应用,也不代表已经过设备实测。 组件片段需接入对应项目;文中自定义函数、示意协议和策略数值需按业务补齐。迁移到 OHOS 时应另外核对适配层支持。
更多推荐


所有评论(0)