如何将元素推入React Hooks状态数组

3
我正在使用react-bootstrap-table2制作HTML表格,我在表格内使用复选框来删除项目。
根据此链接,其中提到了如何获取所选行并执行下一步操作。我的做法是,当我点击任何复选框时,行会被选中,如果我再次选择任何行,则会将其添加到我的状态数组中,如下所示。
onSelect: (row, isSelect, rowIndex, e) => {
        if (isSelect === true) {
            setrowData((rowData) => [...rowData, row]);
        } else {
        //  here i need to do something
        }
    },

我遇到的问题是,当我取消选择某一行时,该值不会从我的数组中删除,在删除时,我拥有所有曾经选择过的数据。

  • 还有一件事与此相关,即当我选中任何一行时,我想要显示删除按钮,当没有行被选中时,我想要隐藏删除按钮,这里的 select 给出了布尔值,但它仅适用于每个选择,当我选择多行时,它会显示出来,但当我取消选择其中任何一行时,删除按钮就会被隐藏。

我为此所做的是类似以下内容

setrowSelect((rowSelect) => [...rowSelect, isSelect]); // this one is inside onSelect callback given by the react-bootstrap-table2 library

           {rowSelect && (
                    <button className="btn Secondary_Button_with_Icon">
                        <i className="ri-upload-cloud-line ri-lg"></i>Register
                    </button>
                )}

我的完整可运行代码


我的解决方案有帮助吗? - SILENT
5个回答

2
在 else 块内使用过滤方法,从数组中移除未选中的元素。
 onSelect: (row, isSelect, rowIndex, e) => {
      if (isSelect === true) {
        setrowData((rowData) => [...rowData, row]);
      } else {
        setrowData((rowData) => rowData.filter((x,i)=>i!==rowIndex))
      }
      setrowSelect((rowSelect) => [...rowSelect, isSelect]);
    },

1
嘿,isSelect还是一样的,当我选择行时,按钮会显示出来,但是当我取消选中所有行时,按钮仍然存在。 - vivek singh

1
请注意,您不需要维护另一个状态来控制“删除”按钮的可见性。
您可以根据rowData状态完美地隐藏/显示Delete按钮。
此外,您编写的用于处理选定行的代码非常有效。只需摆脱rowSelect状态及其处理程序。
并且基于您的rowData内容更新Delete按钮的呈现方式:
{
    rowData.length ? (
        <button className="btn btn-primary" onClick={Delete_device}>
          <i className="ri-upload-cloud-line ri-lg"></i>Delete
        </button>
      )
    : null
}

这是您的分支沙箱

1
尝试将 onSelect 函数更改为以下内容。
  onSelect: (row, isSelect, rowIndex, e) => {
  if (isSelect === true) {
    setrowData((rowData) => [...rowData, row]);
    rowSelect.push(true);
    setrowSelect(rowSelect);
  } else {
    setrowData((rowData) => rowData.filter((x, i) => i !== rowIndex));     
      rowSelect.pop();
      setrowSelect(rowSelect);
  }
}

不行,当我选择两行时,按钮会显示出来,但是当我取消选择一个按钮时,它又被隐藏了,请检查代码沙盒。 - vivek singh
但是它没有更新,请创建您自己的并与我分享链接。 - vivek singh
https://codesandbox.io/s/romantic-diffie-midxt?file=/src/App.js - sivarasan
嘿,你不觉得在 onSelectAll 中传递 setrowSelect([true, true, true]); 是因为有3行吗?但是在这种情况下,行数是动态的,你所做的只是一种权宜之计。 - vivek singh
你可以轻松地使用map循环使其动态化。 - sivarasan
显示剩余3条评论

0
这里有一种实现你想要的方法:
1.将你的数据保存在一个对象中,并添加一个id和isSelect字段。
const data = [
  {
    id: "id-1",
    fname: "john",
    lname: "smith",
    isSelect: false
  },
  {
    id: "id-2",
    fname: "steve",
    lname: "warn",
    isSelect: false
  },
  {
    id: "id-3",
    fname: "michel",
    lname: "clark",
    isSelect: false
  }
];

2.将这些数据传递给useState

const [rowData, setrowData] = useState(data);

3. onSelect:根据ID查找行并设置isSelect字段。

onSelect: (row, isSelect, rowIndex, e) => {
  setrowData((rows) => {
    return rows.map((r) => {
      if (r.id !== row.id) {
        return r;
      }

      return { ...r, isSelect };
    });
  });
},

4. onSelectAllisSelect 设置为所有行

onSelectAll: (isSelect, rows, e) => {
  setrowData((rows) => {
    return rows.map((row) => {
      return { ...row, isSelect };
    });
  });
}

5. 对于Delete_device,只需过滤掉未被选中的数据。
  const Delete_device = () => {
    setrowData((rows) => {
      return rows.filter((row) => !row.isSelect);
    });
  };

6. 对于删除按钮,获取选定的行并计数,如果计数 > 0,则显示该按钮:

const selectedRows = rowData.filter((row) => row.isSelect);

  return (
    <div className="App">
      {selectedRows.length > 0 && (
        <button className="btn btn-primary" onClick={Delete_device}>
          <i className="ri-upload-cloud-line ri-lg"></i>Delete
        </button>
      )}

7. 将状态数据传递给 BootstrapTable

  <BootstrapTable
    bootstrap4
    keyField="fname"
    data={rowData}
    columns={tableData[0].columnsData}
    selectRow={selectRow}
  />

完整示例


不行,这需要我做很多更改,但我仍会尝试实现它。 - vivek singh

0

我更新了你的状态以使用你的数据,并从你的选择逻辑中删除了选择数组。我还对其进行了一些优化。这与你的codesandbox示例有些微小的变化。另外,我建议你使用id。

import React, { useState, useMemo } from "react";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";
import BootstrapTable from "react-bootstrap-table-next";
import "react-bootstrap-table-next/dist/react-bootstrap-table2.min.css";

let tableData = [
  {
    rowsData: [
      {
        fname: "john",
        lname: "smith"
      },
      {
        fname: "steve",
        lname: "warn"
      },
      {
        fname: "michel",
        lname: "clark"
      }
    ],
    columnsData: [
      {
        dataField: "fname",
        text: "First name",
        sort: true
      },
      {
        dataField: "lname",
        text: "last Name",
        sort: true
      }
    ]
  }
];

export default function App() {
  const [rowData, setrowData] = useState(tableData[0].rowsData);
  const [rowSelect, setrowSelect] = useState([]);

  const selectRow = useMemo(
    () => ({
      mode: "checkbox",
      clickToSelect: false,
      classes: "selection-row",
      onSelect: (row, isSelect, rowIndex, e) => {
        setrowSelect((rowData) =>
          isSelect
            ? [...rowData, row]
            : rowData.filter(
                ({ fname, lname }) => row.fname !== fname && row.lname !== lname
              )
        );
        // if (isSelect === true) {
        //   setrowSelect((rowData) => [...rowData, row]);
        // } else {
        //   console.log("onSelect", rowIndex, row, isSelect);
        //   setrowSelect((rowData) =>
        //     rowData.filter(
        //       ({ fname, lname }) => row.fname !== fname && row.lname !== lname
        //     )
        //   );
        // }
      },

      onSelectAll: (isSelect, rows, e) => {
        if (isSelect === true) {
          setrowSelect(rows);
        } else setrowSelect([]);
      }
    }),
    []
  );
  const Delete_device = () => {
    console.log("Delete device", rowData, rowSelect);
    if (rowSelect.length < 1) return;
    setrowData((data) =>
      data.filter(
        ({ fname, lname }) =>
          rowSelect.find((s) => s.fname === fname && s.lname === lname) == null
      )
    );
    setrowSelect([]);
  };
  console.log("App", rowData, rowSelect);
  return (
    <div className="App">
      {rowData.length > 0 && (
        <button className="btn btn-primary" onClick={Delete_device}>
          <i className="ri-upload-cloud-line ri-lg"></i>Delete
        </button>
      )}
      <BootstrapTable
        bootstrap4
        keyField="fname"
        data={rowData}
        columns={tableData[0].columnsData}
        selectRow={selectRow}
      />
    </div>
  );
}

https://codesandbox.io/s/react-bootstrap-table-x-wus5r?file=/src/App.js


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接