You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 21:27:03