我有一个表(父元素),该表可获取用户并将每一行呈现为其自己的组件。表中的行包含复选框。
目标是能够使用复选框并检索选中的复选框。
问题是,当我将函数传递给每一行(子组件)时,要触发将选中的复选框值添加到数组(由选定用户的ID组成),整个组件将被重新渲染,而且真的很滞后前端(显然)。我尝试为每个复选框创建引用,以仅在需要时才检索已选中的复选框-但您不能在循环中使用引用,对于这样的任务似乎不是一件好事。
我的问题是如何在一个表中处理大量复选框,如何将状态保存为已选中的复选框,或在父组件中触发某个函数时能够检索已选中的复选框?
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
)}
这里是一个优化的函数,它将在不重新渲染整个列表和使用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的示例。