从表中删除行不起作用的行

发布于 2025-02-11 14:34:46 字数 1694 浏览 3 评论 0原文

我有一个从此数据

const[formValues,setFormValues] = useState({
sCode:undefined,
sName:undefined,
mList:[{
    sym:"abc",
    minLimit:undefined,
    maxLimit:undefined
},
{
    sym:"xyz",
    minLimit:undefined,
    maxLimit:undefined
}]  });

行呈现的表可以从表中删除行,如果我仅删除最后一行,则每次从页面上的表中删除每次删除,但是状态正在完美更新,即从数据中删除了正确的行(mlist) )。我应该如何纠正它?

const removeRow=(index)=>{
    let Rows = [...formValues.mList];
    Rows.splice(index,1);
    setFormValues({...formValues,mList:[...Rows]})   
}

表代码:

<Table striped  >
<thead>
 <tr><th>S No</th><th>Sym</th><th>Min Limit</th><th>Max Limit</th></tr>
</thead>
<tbody>
    {formValues.mList.map((input,index)=>(
        <tr key={"table-"+index}>
            <td>{index+1}</td>
            <td><TextareaComp id={'mList'+ index+ 'sym'} required={false} name="sym" value={input.sym} onBlur={(evnt)=>(handleTableChange(index, evnt))} /></td>
            <td><TextBoxComp id={'mList'+ index+ 'minLimit'} type="text"  required={false} name="minLimit" value={input.minLimit} onBlur={(evnt)=>(handleTableChange(index, evnt))} /></td>
            <td><TextBoxComp id={'mList'+ index+ 'maxLimit'} type="text"  required={false} name="maxLimit" value={input.maxLimit}  onBlur={(evnt)=>(handleTableChange(index, evnt))} /></td>
            <td><button type="button" className="fa fa-minus btn btn-danger"   onClick={()=>removeRow(index)}></button></td>
        </tr>
     ))}
</tbody>

I have a table rendered from this data

const[formValues,setFormValues] = useState({
sCode:undefined,
sName:undefined,
mList:[{
    sym:"abc",
    minLimit:undefined,
    maxLimit:undefined
},
{
    sym:"xyz",
    minLimit:undefined,
    maxLimit:undefined
}]  });

Rows have button to remove row from table, if I remove random row only last row is removing everytime from table on page , but the state is updating perfectly i.e the correct row is removed from the data(mList). How am I supposed to correct it?

const removeRow=(index)=>{
    let Rows = [...formValues.mList];
    Rows.splice(index,1);
    setFormValues({...formValues,mList:[...Rows]})   
}

Table code :

<Table striped  >
<thead>
 <tr><th>S No</th><th>Sym</th><th>Min Limit</th><th>Max Limit</th></tr>
</thead>
<tbody>
    {formValues.mList.map((input,index)=>(
        <tr key={"table-"+index}>
            <td>{index+1}</td>
            <td><TextareaComp id={'mList'+ index+ 'sym'} required={false} name="sym" value={input.sym} onBlur={(evnt)=>(handleTableChange(index, evnt))} /></td>
            <td><TextBoxComp id={'mList'+ index+ 'minLimit'} type="text"  required={false} name="minLimit" value={input.minLimit} onBlur={(evnt)=>(handleTableChange(index, evnt))} /></td>
            <td><TextBoxComp id={'mList'+ index+ 'maxLimit'} type="text"  required={false} name="maxLimit" value={input.maxLimit}  onBlur={(evnt)=>(handleTableChange(index, evnt))} /></td>
            <td><button type="button" className="fa fa-minus btn btn-danger"   onClick={()=>removeRow(index)}></button></td>
        </tr>
     ))}
</tbody>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晨曦÷微暖 2025-02-18 14:34:46

问题在于,您将映射的数组索引用作React键的一部分,即key = {“ table-” + index}

当您从数组中间删除一行时,例如索引3,向前移动后元素的所有索引,并且由于 仍然存在 index 3处的元素映射时,将分配react key key = {“ table-” + 3},或“ table-3”。 React检查当前渲染周期映射索引的钥匙值与上一个渲染循环所使用的密钥,并且因为它们在恢复任何内容时都是相同的React保释金。您正在看到formValues.mlist数组的效果短,这就是为什么您会看到删除最后一个元素的原因,react耗尽了元素以渲染并将键分配给。

使用对其代表的数据进行固有的反应键值或“粘性”。通常,您将使用任何独特的属性。例如,如果sym属性在fieldValues.mlist数组数据集中是唯一的,则将被用作React键。

示例:

{formValues.mList.map((input, index) => (
  <tr key={"table-" + input.sym}> // "table-abc", "table-xyz", etc
    <td>{index+1}</td>
    <td>
      <TextareaComp
        id={'mList' + index + 'sym'}
        required={false}
        name="sym"
        value={input.sym}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'minLimit'}
        type="text"
        required={false}
        name="minLimit"
        value={input.minLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'maxLimit'}
        type="text"
        required={false}
        name="maxLimit"
        value={input.maxLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <button
        type="button"
        className="fa fa-minus btn btn-danger"
        onClick={() => removeRow(index)}
      />
    </td>
  </tr>
))}

如果sym属性不是唯一的,并且没有其他合适的属性,那么我建议将GUID注入您的mList数组数据。为此, uuid 软件包非常适合生成全球唯一的标识符。

示例:

import { v4 as uuidV4 } from 'uuid';

...

const fetchData = () => {
  const mListData = fetch(......);
  const mListDataWithGuid = mListData.map(el => ({
    ...el,
    id: uuidV4(), // <-- inject GUID value
  }));
};

...

{formValues.mList.map((input, index) => (
  <tr key={"table-" + input.id}> // "table-lksdlk-0234lknsf-wef", etc
    <td>{index+1}</td>
    <td>
      <TextareaComp
        id={'mList' + index + 'sym'}
        required={false}
        name="sym"
        value={input.sym}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'minLimit'}
        type="text"
        required={false}
        name="minLimit"
        value={input.minLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'maxLimit'}
        type="text"
        required={false}
        name="maxLimit"
        value={input.maxLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <button
        type="button"
        className="fa fa-minus btn btn-danger"
        onClick={() => removeRow(index)}
      />
    </td>
  </tr>
))}

其他建议

我通常建议避免使用array.protype.splice,因为它会突变其操作的数组。您应该使用功能状态更新来正确更新任何以前的状态,并使用唯一的字段属性而不是索引从数组中删除元素。使用array.prorotype.filter从数组 返回新数组参考。

示例:

const removeRow = (sym) => {
  setFormValues(formValues => ({
    ...formValues,
    mList: formValues.mList.filter(el => el.sym !== sym)
  }));
};

将唯一标识符传递给回调:

<button
  type="button"
  className="fa fa-minus btn btn-danger"
  onClick={() => removeRow(input.sym)}
/>

The issue is that you are using the mapped array index as part of the React key, i.e. key={"table-" + index}.

When you remove a row from the middle of the array, say index 3, all the indices of the elements after shift forward, and since there is still an element at index 3 when it's mapped it'll be assigned the React key key={"table-" + 3}, or "table-3". React checks the key values for the mapped index from the current render cycle against the key used from the previous render cycle and since they are the same React bails on rerendering anything. You are seeing the effect of the formValues.mList array being 1 element shorter and this is why you see the last element removed, React ran out of elements to render and assign keys to.

Use React key values that are intrinsic, or "sticky" to the data they are representing. Generally you would use any unique property for this. For example, if the sym property is unique within the fieldValues.mList array dataset it would be a good candidate to be used as a React key.

Example:

{formValues.mList.map((input, index) => (
  <tr key={"table-" + input.sym}> // "table-abc", "table-xyz", etc
    <td>{index+1}</td>
    <td>
      <TextareaComp
        id={'mList' + index + 'sym'}
        required={false}
        name="sym"
        value={input.sym}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'minLimit'}
        type="text"
        required={false}
        name="minLimit"
        value={input.minLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'maxLimit'}
        type="text"
        required={false}
        name="maxLimit"
        value={input.maxLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <button
        type="button"
        className="fa fa-minus btn btn-danger"
        onClick={() => removeRow(index)}
      />
    </td>
  </tr>
))}

If the sym property isn't unique, and there's no other suitable property then I suggest injecting a GUID into your mList array data. For this the uuid package is great at generating globally unique identifiers.

Example:

import { v4 as uuidV4 } from 'uuid';

...

const fetchData = () => {
  const mListData = fetch(......);
  const mListDataWithGuid = mListData.map(el => ({
    ...el,
    id: uuidV4(), // <-- inject GUID value
  }));
};

...

{formValues.mList.map((input, index) => (
  <tr key={"table-" + input.id}> // "table-lksdlk-0234lknsf-wef", etc
    <td>{index+1}</td>
    <td>
      <TextareaComp
        id={'mList' + index + 'sym'}
        required={false}
        name="sym"
        value={input.sym}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'minLimit'}
        type="text"
        required={false}
        name="minLimit"
        value={input.minLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <TextBoxComp
        id={'mList' + index + 'maxLimit'}
        type="text"
        required={false}
        name="maxLimit"
        value={input.maxLimit}
        onBlur={(evnt) => handleTableChange(index, evnt)}
      />
    </td>
    <td>
      <button
        type="button"
        className="fa fa-minus btn btn-danger"
        onClick={() => removeRow(index)}
      />
    </td>
  </tr>
))}

Additional suggestion

I typically recommend avoiding the use of Array.prototype.splice as it mutates the array it operates over. You should use a functional state update to correctly update from any previous state, and use the unique field property instead of the index to remove the element from the array. Use Array.prorotype.filter to filter elements from the array and return a new array reference.

Example:

const removeRow = (sym) => {
  setFormValues(formValues => ({
    ...formValues,
    mList: formValues.mList.filter(el => el.sym !== sym)
  }));
};

Pass the unique identifier to the callback:

<button
  type="button"
  className="fa fa-minus btn btn-danger"
  onClick={() => removeRow(input.sym)}
/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文