React中fetch请求成功后如何正确重置手机号状态数组?
解决React提交验证后手机号数组时的空数组问题
问题核心在于React的state更新是异步批量处理的:你在procPhoneNos里通过forEach多次调用setValidatedPhoneNos更新数组,但这些更新不会立刻生效。当你紧接着调用addPhoneNosToDB时,validatedPhoneNos还是原来的旧值(初始为空),所以提交的自然是空数据;如果去掉重置代码,第二次调用时才会拿到第一次更新后的state,导致旧数据残留。
直接改代码就行,不用依赖state传递刚生成的验证数组,而是在procPhoneNos里先把所有验证后的号码整理成临时数组,直接传给addPhoneNosToDB,同时确保只有请求成功后才清空state:
const [phoneNos, setPhoneNos] = useState('') // 输入框的值 const [validatedPhoneNos, setValidatedPhoneNos] = useState([]); // 存储已验证号码的数组 // 接收验证后的号码数组作为参数,不再依赖state function addPhoneNosToDB (validatedList) { fetch(`end_point`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, mode: 'cors', body: JSON.stringify({ somefield: fieldValue, list: validatedList // 直接用传入的数组,避免异步state问题 }), }).then(r => { toast.success('列表已添加成功') setPhoneNos(''); setValidatedPhoneNos([]) // 请求成功后才清空数组 }).catch(err => toast.warning(err)) } // 验证并格式化号码的函数 function procPhoneNos () { if (!phoneNos) { toast.warning("请至少输入一个手机号") return } const countryCodePattern = /^(?:\+?234|0)?(7\d{8})$/; const phoneNumberPattern = /^(0|\+?234)(\d{10})$/; const inputList = phoneNos.split(',').map(phoneno => phoneno.trim()); const validatedList = []; let hasInvalid = false; // 用for循环替代forEach,方便中途终止 for (const num of inputList) { if (num.match(countryCodePattern)) { validatedList.push(num); } else if (num.match(phoneNumberPattern)) { validatedList.push(num.replace(phoneNumberPattern, '234$2')); } else { hasInvalid = true; break; } } if (hasInvalid) { toast.warning("存在格式不正确的手机号") return; } // 可选:更新state用于UI展示 setValidatedPhoneNos(validatedList); // 直接传递验证好的数组给提交函数 addPhoneNosToDB(validatedList); }
关键修改说明
- 不再多次调用
setValidatedPhoneNos,而是用临时数组validatedList一次性收集所有有效号码,避免异步更新的延迟 - 把
validatedList作为参数传给addPhoneNosToDB,彻底绕开state异步更新导致的数据不一致问题 - 优化错误处理:遇到无效号码立刻终止处理,避免部分有效号码被误处理
- 仅在fetch请求成功后才清空输入框和验证数组的state,确保数据提交成功后才重置
这样修改后,既能保证提交的是最新的验证结果,又能实现“成功后重置”的需求,完全不需要使用useEffect。
内容的提问来源于stack exchange,提问作者deXtro
相关产品推荐
相关产品推荐

