如何更新关联Redux状态的输入框?输入框无法输入问题求助
解决React表格输入框无法输入的问题
问题背景
我实现了一个展示记录并支持基础数据更新的表格,状态下拉框功能正常,但MatterNo对应的输入框无法输入内容。相关代码如下:
表格渲染代码
const renderTableRows = () => { return invoices?.map((invoice, i) => ( <tr key={i} onClick={() => handleClick(invoice.ID)} className={`${InvoiceStatus_Category(invoice.Status)}`} > <td> <span className={`${InvoiceStatus(invoice.DaysFromDueDate)}`}>O</span> </td> <td> <select name="status" onChange={(e) => handleStatusOnChange(e, invoice.ID)} value={invoice.Status} placeholder="Change Status" > <option value={invoiceStatus}></option> <option value="Paid">Paid</option> <option value="Post&Hold">Post&Hold</option> <option value="Instructions">Instructions</option> </select> </td> <td className="choice"> <input key={i} className="matter-input" name="matterInput" type="text" onChange={onChange} maxLength={6} value={invoice.MatterNo} /> </td> <td> <button className="matter-button" onClick={() => { buttonOnClick(invoice.ID, matter); setMatter(""); }} > Add Matter </button> </td> </tr> )); };
onChange事件代码
const onChange = (e, i) => { const { name, value } = e.target; setMatter(value); };
按钮更新API代码
const buttonOnClick = (i, mat) => { if (mat > 0) { axios({ method: "put", url: "http://localhost:64198/api/UpdateMatter", data: { InvoiceID: i, Matter: mat, }, headers: { "Content-Type": "application/json" }, }).then((res) => { dispatch(fetchAsyncInvoices()); setMatter(""); }); setMatter(""); window.location.reload(false); } };
问题原因
输入框的value绑定的是原始数据源中的invoice.MatterNo,但onChange事件仅更新了全局的matter状态,并未同步修改数据源对应项的MatterNo值。每次输入时组件重新渲染,输入框会被原始的invoice.MatterNo覆盖,导致无法输入内容。
解决方案
根据数据源的维护方式,提供两种可行方案:
方案一:用独立状态维护每行输入值(适合数据源来自Redux/父组件)
- 初始化一个对象状态,存储每个发票ID对应的输入值:
const [matterValues, setMatterValues] = useState({});
- 修改输入框的
value和onChange,绑定到对应发票ID的状态:
<input key={i} className="matter-input" name="matterInput" type="text" onChange={(e) => setMatterValues(prev => ({...prev, [invoice.ID]: e.target.value}))} maxLength={6} value={matterValues[invoice.ID] || invoice.MatterNo} />
- 修改按钮点击事件,使用当前行的输入值,并清空对应状态:
<button className="matter-button" onClick={() => { const currentValue = matterValues[invoice.ID] || invoice.MatterNo; buttonOnClick(invoice.ID, currentValue); setMatterValues(prev => ({...prev, [invoice.ID]: ""})); }} > Add Matter </button>
- 优化
buttonOnClick,去掉多余的页面刷新(dispatch已重新获取数据):
const buttonOnClick = (i, mat) => { if (mat) { // 改为检查值是否存在,兼容字符串类型 axios({ method: "put", url: "http://localhost:64198/api/UpdateMatter", data: { InvoiceID: i, Matter: mat, }, headers: { "Content-Type": "application/json" }, }).then((res) => { dispatch(fetchAsyncInvoices()); }); } };
方案二:直接修改本地数据源(适合invoices是本地useState状态)
如果invoices是通过useState维护的本地状态,可直接在onChange时更新对应项的MatterNo:
- 修改
onChange事件:
const onChange = (e, invoiceId) => { const newValue = e.target.value; setInvoices(prevInvoices => prevInvoices.map(inv => inv.ID === invoiceId ? {...inv, MatterNo: newValue} : inv ) ); };
- 更新输入框的
onChange绑定:
<input key={i} className="matter-input" name="matterInput" type="text" onChange={(e) => onChange(e, invoice.ID)} maxLength={6} value={invoice.MatterNo} />
这样输入框就能正常输入,且值会实时同步到数据源中,点击按钮时直接使用invoice.MatterNo即可。
内容的提问来源于stack exchange,提问作者cruz
相关产品推荐
相关产品推荐

