【问题标题】:How to push elements to react hooks state array如何推动元素反应钩子状态数组
【发布时间】:2020-09-09 12:51:08
【问题描述】:

我正在使用react-bootstrap-table2 制作 HTML 表格,我正在使用表格中的复选框来删除项目。

所以根据This link,提到了如何获取选定的行然后执行下一部分,这里我正在做的是当我点击任何复选框行时,如果我再次选择任何行我正在将数组添加到我的状态中,如下所示

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>
                )}

My full working code

【问题讨论】:

  • 我的解决方案有帮助吗?

标签: javascript reactjs react-hooks react-bootstrap-table


【解决方案1】:

在 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]);
    },

【讨论】:

  • 嘿,isSelect 还是一样,当我选择行按钮时显示,但是当我取消选中所有行时,按钮仍然存在
【解决方案2】:

请注意,您不需要维护另一个状态来控制Delete 按钮的可见性。

您可以根据rowData 状态完美隐藏/显示删除。

您为处理选定行编写的代码也运行良好。只需摆脱 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
}

这是你的forked sandbox

【讨论】:

    【解决方案3】:

    尝试像这样更改 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);
      }
    }
    

    【讨论】:

    • 不,它不起作用,当我选择两行按钮时会显示,但是当我取消选择一个按钮时再次设置为隐藏请检查代码沙箱
    • 我已经更新了 sandbox.now 它的工作 onSelect: (row, isSelect, rowIndex, e) => { if (isSelect === true) { setrowData((rowData) => [...行数据,行]); rowSelect.push(true);设置行选择(行选择); } else { setrowData((rowData) => rowData.filter((x, i) => i !== rowIndex));行选择.pop();设置行选择(行选择); } }
    • 你的代码沙箱在哪里?我已经尝试了您编辑的答案,但它没有按预期工作。
    • 但那里没有更新,请创建自己的并分享链接
    【解决方案4】:

    这是实现您想要的一种方法:

    1.将您的数据保存在一个对象中,并添加 idisSelect 字段

    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.onSelectAll 在所有行上设置isSelect

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

    5.for 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}
      />
    

    Complete example

    【讨论】:

    • 不,不,我需要做很多改变,但我仍然会尝试实现这一点。
    【解决方案5】:

    我更新了您的状态以使用您的数据,并从您的选择逻辑中删除了选择数组。我也对其进行了一些优化。它与您的代码和框示例的微小变化。另外,我建议您使用 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

    【讨论】:

      猜你喜欢
      • 2021-10-23
      • 2020-03-19
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-12
      相关资源
      最近更新 更多