处理 200 多个复选框,将它们存储在状态 [英] Handle more than 200 checkboxes storing them in state

查看:36
本文介绍了处理 200 多个复选框,将它们存储在状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

const UserRow = ({checked, setChecked) =>(//渲染字段//...<Checkbox checked={checked} onChange={() =>setChecked()}/>)const ParentComponent = () =>{const [users, setUsers] = useState();const [checkedCheckboxes, setCheckedCheckboxes] = useState([]);useEffect(() => {//获取用户setUsers(fetchedUsers);});const rows = users.map(user => <UserRow键={id}名称={用户名}电子邮件={user.email}选中={checkedCheckboxes.includes(id)}setChecked={setCheckedCheckboxes(checkedCheckboxes.concat(id)}/>;返回 (//渲染表{rows}//插入行)}

解决方案

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

import React, { useEffect, useState } from 'react';const Parent = () =>{//列表在父级中创建和维护const [list, setList] = useState([{ id: 1, val: true },{ id: 2, val: true },]);//toggle 是 id 指示要切换的项目const [toggle, setToggle] = useState();useEffect(() => {如果(切换){//设置切换不会重新渲染,直到//函数完成所以没有无限循环设置切换();//这里我们可以从列表中切换项目设置列表(list.map(item =>item.id === 切换?{ ...item, val: !item.val }: 物品));}}, [列表, 切换]);//将父容器与父表示结合//为简单起见返回 (<div>{list.map(item => (<物品容器键={item.id}项目={项目}//当项目被点击时传递setToggleitemClicked={setToggle}/>))}

);};const ItemContainer = React.memo(function Item({物品,项目点击,}) {//切换 id 为 1 的项目不会记录//对于 id 为 2 的项目console.log('in item render:', item.id);返回 (<pre onClick={() =>itemClicked(item.id)}>{JSON.stringify(item, undefined, 2)}

);});导出默认父级;

这里是一个如何使用 useReducer 的例子.

I have a table (parent element) which fetches users and render each row as it's own component. Row in a table contains checkbox.

Goal is to be able to use checkboxes and retrieve checked checkboxes.

Problem is that when i'm passing function to each row (child component), to trigger adding checked checkbox value to the array (which consists of id's of selected users), whole component gets re-rendered and it is really laggy on the front-end (obviously). I tried to create refs for every checkbox to retrieve checked checkboxes only when needed - but you can't use Refs in a loop and seem to be not a good thing to do for such a task.

My question is how to handle lots of checkboxes in one table, storing checked checkboxes in a state or being able to retrieve checked checkboxes when triger a function in parent component?

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

解决方案

Here is an optimized function that will toggle an item without re rendering the entire list and using a list from 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 is an example of how to do it with useReducer.

这篇关于处理 200 多个复选框,将它们存储在状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆