React中点击订单校验按钮后动态表格无法重新填充刷新问题
问题根因
你的场景存在两个核心问题:
- 表格内的商品输入框使用了
defaultValue属性,该属性仅在组件首次挂载渲染时生效,后续订单更新后,因为同索引商品的fakeId完全一致,React会判定为相同组件直接复用,不会重新计算赋值,导致新订单的数据无法更新到输入框 - 订单号输入框为不受控组件,没有绑定状态监听逻辑,输入新订单号后不会自动触发校验接口,必须手动点击按钮才会拉取新数据
修复方案
1. 修复表格输入框不更新的问题
将输入框的defaultValue改为value,改为受控组件,如果允许用户修改商品名称,同步添加onChange事件处理表单值更新:
// 表格内商品输入框修改示例 <input required value={this.defaultValue(product.fakeId, 'productName')} onChange={(e) => this.handleProductChange(product.fakeId, 'productName', e.target.value)} id={`productName${product.fakeId}`} name="productName" type="text" className="form-control" style={{ borderColor: '#001689' }} autoComplete="off" list="suggestions" />
同步添加handleProductChange方法处理用户输入的值更新:
handleProductChange = (fakeId, field, value) => { const newProductsPackaging = this.state.productsPackaging.map(item => { if (item.fakeId === fakeId) { return { ...item, [field]: value } } return item }) this.setState({ productsPackaging: newProductsPackaging }) }
2. 修复组件复用导致的渲染异常
修改fakeId的生成规则,加入当前订单号作为唯一标识,避免不同订单的同索引商品复用同一个组件:
// validateOrder方法内修改fakeId生成逻辑 for (let index = 0; index < res.products.length; index++) { // 用当前输入的cai值拼接索引作为唯一fakeId const element = { fakeId: `${cai}-id-${index}`, articleId: res.products[index].Articulo_Id, originalAmountPills: res.products[index].amount }; const element2 = { ...res.products[index], fakeId: `${cai}-id-${index}` }; tempProducts.push(element); tempProductsPackaging.push(element2); }
3. (可选)实现输入新订单号自动校验
如果需要实现输入订单号后自动拉取数据,不需要手动点击按钮,可以将订单输入框改为受控组件,绑定状态并添加防抖触发校验逻辑:
首先在state里添加cai字段存储输入的订单号:
// 构造函数内添加 this.state = { // 其他原有状态 cai: '' }
修改订单输入框的绑定逻辑:
<input required id="cai" type="text" value={this.state.cai} onChange={this.handleCaiChange} className="form-control text-primary" style={{ borderColor: '#001689' }} aria-describedby="inputGroup-sizing-sm" aria-label="Small" placeholder="CAI" autoComplete="off" />
添加handleCaiChange方法防抖触发校验:
handleCaiChange = (e) => { const value = e.target.value this.setState({ cai: value }) // 防抖500ms,输入停止后自动触发校验 clearTimeout(this.caiTimer) this.caiTimer = setTimeout(() => { this.validateOrder() }, 500) } // 组件卸载时清除定时器 componentWillUnmount() { clearTimeout(this.caiTimer) }
同时修改validateOrder方法内的取值逻辑,直接从state拿cai而不是从DOM取:
validateOrder = () => { const { products, productsPackaging, anotherCai, cai } = this.state; // 删掉原来的const cai = document.getElementById('cai').value; // 其余原有逻辑不变 }
内容的提问来源于stack exchange,提问作者frustratedProgrammer
相关产品推荐
相关产品推荐

