【问题标题】:React-table: State doesn't change as expected, and table doesn't updateReact-table:状态未按预期更改,表未更新
【发布时间】:2020-05-30 12:43:01
【问题描述】:

代码沙盒示例:https://codesandbox.io/s/react-table-state-not-updating-hmquq?file=/src/App.js

我正在使用react-table 包(版本 7.1.0)。

我有一个表格,其中显示了一些发票,如下所示:

用户应该能够使用selected 复选框选择部分或全部这些项目。

selected 字段不是数据的一部分。但是,当用户点击selected 复选框时,该字段应该切换并且应该填充一个存储文档编号的数组。

为了存储文档编号,我有一个有状态的 getter 和 setter:

const [selectedInvoiceIds, setSelectedInvoiceIds] = useState([]);

为了填充该字段,我试图从复选框的onChange 简单地将文档编号添加到数组中:

      {
        Header: "Selected",
        accessor: "selected",
        Cell: item => {
          const { documentNumber } = item.row.values;
          return (
            <input
              type="checkbox"
              checked={selectedInvoiceIds.includes(documentNumber)}
              onChange={() => {
                setSelectedInvoiceIds([...selectedInvoiceIds, documentNumber]);
              }}
            />
          );
        }
      }

当第一次单击复选框时,selectedInvoiceIds 将被填充:

selectedInvoiceIds: ["706942"]

问题是

  • 尽管复选框上有这个道具,但表格不会更新以反映状态变化:
checked={selectedInvoiceIds.includes(documentNumber)}
  • selectedInvoiceIds 值会在添加另一个文档编号时被覆盖,而不是被添加到其中,就好像状态正在重新初始化为介于两者之间的 []

能否解释为什么会出现这些状态问题以及如何解决?

我知道 react-table 公开了 useTableState 值,但我不知道如何将其应用于此用例。

代码沙盒示例:https://codesandbox.io/s/react-table-state-not-updating-hmquq?file=/src/App.js

【问题讨论】:

    标签: javascript reactjs state react-table


    【解决方案1】:

    这段代码有多个问题:

    // 1) updates to state should should use callback function if it uses prv state
    
     return (
                <input
                  type="checkbox"
                  checked={selectedInvoiceIds.includes(documentNumber)}
                  onChange={() => {
                    setSelectedInvoiceIds(prvSelectedInovicesId => [...prvSelectedInovicesId, documentNumber]);
                  }}
                />
              );
    
    // 2) also columns is using useMemo, however not providing dependencies, so columns are not being updated when the selectedInvociesIds state gets updated
    
    // 3) you are not yet handling the toggle, this mean you are just always just adding to the array and not removing from it
    
    

    这是一个工作版本代码沙箱 https://codesandbox.io/s/react-table-state-not-updating-wkri3?file=/src/App.js

    【讨论】:

    • 同意第 3 点 - 所以对象会比数组更合理,然后可以将其更改为 {...selectedInovicesIds, documentNumber: !selectedInovicesIds[documentNumber]} 所以切换就足够了
    • @DmitryReutov 是的,一个对象会更好,在性能方面也是如此,一个数组意味着他将为每个条目做 n 个工作,有 n 个条目,所以他正在做 n* *2 总工作量。话虽如此,我什至会使用 Set,因为它提供了更好的语义
    • 性能,我想,在这种特殊情况下不值得一提,因为即使在 10 000 个元素中搜索也会在现代设备上花费如此短的时间,以至于用户不会注意到差异,但会反对or may be Set 对于这种情况当然更合理
    • @DmitryReutov 是的,我同意,除非已经存在性能问题,否则可读性优于性能,除了这将是过早的优化,但是我认为如果数组大小足够大,移动用户设备会注意到一些迟缓
    【解决方案2】:

    因为useMemo,将你的数组添加到最后一个参数

    const columns = React.useMemo(
    // ....
    ,
    [selectedInvoiceIds]
      );
    

    由于我们需要切换复选框,因此将选定的 id 保留在对象而不是数组中并将其更新为 this 更合理

    setSelectedInvoices({
      ...selectedInovicesIds, 
      documentNumber: !selectedInovicesIds[documentNumber]}
    ) 
    

    所以它会切换标记

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      • 2015-06-11
      相关资源
      最近更新 更多