【问题标题】:Handle more than 200 checkboxes storing them in state处理超过 200 个以状态存储它们的复选框
【发布时间】:2019-09-29 19:33:47
【问题描述】:

我有一个表(父元素),它获取用户并将每一行呈现为它自己的组件。表中的行包含复选框。

目标是能够使用复选框并检索选中的复选框。

问题是,当我将函数传递给每一行(子组件)时,为了触发将选中的复选框值添加到数组(由选定用户的 id 组成),整个组件被重新渲染,它真的很滞后在前端(显然)。我尝试为每个复选框创建 refs,以便仅在需要时检索选中的复选框 - 但是您不能在循环中使用 Refs,而且对于这样的任务似乎不是一件好事。

我的问题是如何处理一个表中的大量复选框,将选中的复选框存储在一个状态中,或者在触发父组件中的函数时能够检索选中的复选框?

const UserRow = ({checked, setChecked) => (
  // render fields
  // ...
  <Checkbox checked={checked} onChange={() => setChecked()} />
)

const ParentComponent = () => {
const [users, setUsers] = useState();
const [checkedCheckboxes, setCheckedCheckboxes] = useState([]);

useEffect(() => {
  // fetch users
  setUsers(fetchedUsers);
});

const rows = users.map(user => <UserRow
        key={id}
        name={user.name}
        email={user.email}
        checked={checkedCheckboxes.includes(id)}
        setChecked={setCheckedCheckboxes(checkedCheckboxes.concat(id)}
      />;

return (
  // render table
  {rows} // inset rows
)}

【问题讨论】:

  • 你能发布一些代码,或者一些工作示例吗?
  • 你是在使用类还是函数式组件,可以使用 react hooks 吗?
  • @HMR 我正在使用带有钩子的功能组件。
  • 查看这篇文章 - itnext.io/handling-large-lists-and-tables-in-react-238397854625 你可能会发现它很有用。
  • 为什么要跟踪所有复选框的状态?为什么不从一个空数组开始并在检查时添加选定的键?我还记得读过关于复选框导致不必要的重新渲染的问题。您可能希望将您的复选框包装在 memoized 组件中,以尝试防止任何过度的重新渲染。

标签: javascript reactjs


【解决方案1】:

这是一个优化的函数,它可以在不重新渲染整个列表并使用来自 useState 的列表的情况下切换项目:

import React, { useEffect, useState } from 'react';

const Parent = () => {
  //list is created and maintained in parent
  const [list, setList] = useState([
    { id: 1, val: true },
    { id: 2, val: true },
  ]);
  //toggle is id to indicate what item to toggle
  const [toggle, setToggle] = useState();
  useEffect(() => {
    if (toggle) {
      //setting toggle will not re render until
      //  function is finished so no infinite loop
      setToggle();
      //here we can toggle the item from the list
      setList(
        list.map(item =>
          item.id === toggle
            ? { ...item, val: !item.val }
            : item
        )
      );
    }
  }, [list, toggle]);
  //combining parent container with parent presentational
  //  for simplicity
  return (
    <div>
      {list.map(item => (
        <ItemContainer
          key={item.id}
          item={item}
          //pass setToggle as item clicked
          itemClicked={setToggle}
        />
      ))}
    </div>
  );
};
const ItemContainer = React.memo(function Item({
  item,
  itemClicked,
}) {
  //toggeling item with id 1 will not log
  //  for item with id 2
  console.log('in item render:', item.id);
  return (
    <pre onClick={() => itemClicked(item.id)}>
      {JSON.stringify(item, undefined, 2)}
    </pre>
  );
});

export default Parent;

Here 是一个如何使用 useReducer 的示例。

【讨论】:

  • 我找到了使用 useReducer + useMemo + useCallback 的解决方案。很快就会发布我的解决方案。感谢您的宝贵时间!
  • @Src 很想看到你的解决方案(尽管这已经有一年了)
猜你喜欢
  • 2022-01-01
  • 2018-03-18
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-19
相关资源
最近更新 更多