setState 函数未有效更新行变量,因此未反映在 UI?

setState funtion is not validly updating the rows variable and hence it is not reflecting in the UI?

此代码的目的是类似于待办事项列表功能。添加按钮应该将另一个数组对象添加到由 rows.map 迭代并通过显示另一个 TextField 反映在 UI 中的行数组。减去按钮应该通过将其 id 作为参数发送到名为 DeleteMetric(id) 的函数来删除所选行。但是,当单击减法按钮时,它会删除最后添加的数组元素,而不管发送的 ID 是什么(它发送正确的 ID,因为我已经在控制台记录并测试了它。)我希望删除 ID 已被删除的行作为参数发送,而不是最后添加的参数。预先感谢您对我的帮助。

状态是这样定义的。

let [rows, setRows] = useState([
    {
        id: 1090,
        name: 'Enter Name',
        unit: 'Enter Unit'
    },
    {
        id: 3000,
        name: 'RISHAV',
        unit: 'Unit'
    }
]);[enter image description here][1]

SubmitMetric 函数

const submitMetric = () => {
    const c = Math.floor(Math.random() * 1000);
    const newMetric = {
        id: c,
        name: name,
        unit: unit
    }
    setRows([...rows, newMetric]);
}

我的 DeleteMetric 函数是

const deleteMetric = async (id) => {
    await setRows(rows.filter((element) => {
        return element.id !== id;
    }));
}

它产生了相同的结果,所以我将函数更改为显式改变 rows 变量,这也不起作用。

现在的 DeleteMetric 函数。

const deleteMetric = async (id) => {
    rows = await rows.filter((element) => {
        return element.id !== id;
    });
    await setRows(rows);
}

返回的 JSX。

return (
    <div>
        {rows.map((row) => (
            <Table>
                <TableRow>
                    <TableCell>
                        <FormControl className="form-full-width">
                            <TextField variant="outlined" defaultValue={row.id}/>
                        </FormControl>
                    </TableCell>
                    <TableCell>
                        <FormControl className="form-full-width">
                            <TextField variant="outlined" defaultValue={row.unit}/>
                        </FormControl>
                    </TableCell>
                    <TableCell align='center'>
                        <IconButton onClick={submitMetric}>
                            <AddIcon/>
                        </IconButton>
                    </TableCell>
                    <TableCell align='center'>
                        <IconButton onClick={async () => {
                            await deleteMetric(row.id);
                        }
                        }>
                            <RemoveIcon/>
                        </IconButton>
                    </TableCell>
                </TableRow>
            </Table>
        ))}
        <div align='center' className='margin-1'>
            <Button variant="contained" color="primary">
                Submit
            </Button>
        </div>
    </div>
);

}

你不应该改变数组。当您在 deleteMetric() 中重新分配过滤后的数组时,您修改了 rows 状态。尝试以下,它正确使用状态挂钩而不改变它:

const deleteMetric = (id) => {
  setRows(rows.filter((el) => el.id !== id));
}

您还需要删除代码中的每个 async/await。没有一个是必要的。

function App() {
  let [rows, setRows] = React.useState([
    {
      id: 1090,
      name: "Name 1",
      unit: "Unit 1"
    },
    {
      id: 3000,
      name: "Name 2",
      unit: "Unit 2"
    },
    {
      id: 8439,
      name: "Name 3",
      unit: "Unit 3"
    }
  ]);

  const submitMetric = () => {
    const c = Math.floor(Math.random() * 1000);
    const newMetric = {
      id: c,
      // only added these as I don't know what name 
      // and unit was in your original code
      name: `Name ${c}`,
      unit: `Unit ${c}`
    };
    setRows([...rows, newMetric]);
  };

  const deleteMetric = (id) => {
    setRows(rows.filter((el) => el.id !== id));
  };

  return (
    <div>
      {rows.map((row) => (
        <table key={row.id}>
          <tbody>
            <tr>
              <td>
                <label className="form-full-width">
                  <input defaultValue={row.id} />
                </label>
              </td>
              <td>
                <label className="form-full-width">
                  <input defaultValue={row.unit} />
                </label>
              </td>
              <td align="center">
                <button onClick={submitMetric}>Add</button>
              </td>
              <td align="center">
                <button onClick={() => deleteMetric(row.id)}>Remove</button>
              </td>
            </tr>
          </tbody>
        </table>
      ))}
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>