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

如何更新关联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/父组件)

  1. 初始化一个对象状态,存储每个发票ID对应的输入值:
const [matterValues, setMatterValues] = useState({});
  1. 修改输入框的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}
/>
  1. 修改按钮点击事件,使用当前行的输入值,并清空对应状态:
<button
  className="matter-button"
  onClick={() => {
    const currentValue = matterValues[invoice.ID] || invoice.MatterNo;
    buttonOnClick(invoice.ID, currentValue);
    setMatterValues(prev => ({...prev, [invoice.ID]: ""}));
  }}
>
  Add Matter
</button>
  1. 优化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:

  1. 修改onChange事件:
const onChange = (e, invoiceId) => {
  const newValue = e.target.value;
  setInvoices(prevInvoices => 
    prevInvoices.map(inv => 
      inv.ID === invoiceId ? {...inv, MatterNo: newValue} : inv
    )
  );
};
  1. 更新输入框的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 01:37:29