React Native动态长度数组的TextInput如何聚焦,增删购物车项useRef报错解决?
问题根源
- 违反了React Hook使用规则:Hook只能在React组件顶层调用,你封装的
inputRef函数中循环调用useRef,当购物车项增删导致cartItems长度变化时,useRef的调用次数会和上一次渲染不一致,React就会抛出渲染次数不匹配的错误,这是你报错的核心原因。 - 用数组索引作为ref的关联标识,删除购物车中间项后,后续所有商品的索引都会前移,ref和实际输入框的对应关系完全错乱,会出现聚焦错位、调用已卸载组件方法的报错。
解决方案
1. 改用唯一标识存储ref
组件顶层只调用一次useRef,用Map结构存储所有输入框的ref,以商品唯一product_id作为key,不受索引变化影响:
// 组件顶层调用,仅执行一次 const inputRefs = useRef(new Map());
2. 修改TextInput的ref绑定和聚焦逻辑
渲染时将每个输入框的实例按product_id存入Map,提交编辑时直接通过下一项的product_id取ref调用聚焦:
<TextInput placeholder="Qty" placeholderTextColor="#676767" style={InputStyleWithoutBorder} onChangeText={(quantity) => inputQuantity(item.product_id, quantity, defaultUnit.default)} keyboardType={"numeric"} value={item.quantity} returnKeyType={index === cartItems.length - 1 ? "done" : "next"} blurOnSubmit={index === cartItems.length - 1 ? true : false} // 按product_id存储ref ref={(el) => inputRefs.current.set(item.product_id, el)} onSubmitEditing={() => { inputQuantity(item.product_id, item.quantity); // 不是最后一项就聚焦下一个输入框 if (index < cartItems.length - 1) { const nextProductId = cartItems[index + 1].product_id; // 可选链避免ref不存在时报错 inputRefs.current.get(nextProductId)?.focus(); } }} />
3. 可选:删除商品时清理ref
删除购物车项时同步清理Map中对应的ref,避免内存泄漏:
const deleteCartItem = (productId) => { // 原有删除购物车项的逻辑 inputRefs.current.delete(productId); }
内容的提问来源于stack exchange,提问作者Zubair Khan
相关产品推荐
相关产品推荐

