我有一个页面,其中有Listings。用户可以检查此列表中的项目。
每当用户检查某个东西时,它就会被添加到全局声明的集合中(每个项目的唯一ID都被添加到该集合中(。此集合中的ID需要由一个单独的组件(让我们称之为PROCESS_COMPONENT
(访问,该组件处理ID存在于该集合中的特定Listings。
我的Listings代码大致如下:
import React from "react";
import { CheckBox, PROCESS_COMPONENT } from "./Process.jsx";
const ListItem = ({lItem}) => {
return (
<>
//name,image,info,etc.
<CheckBox lId={lItem.id}/>
</>
)
};
function Listings() {
// some declarations blah blah..
return (
<>
<PROCESS_COMPONENT /> // Its a sticky window that shows up on top of the Listings.
//..some divs and headings
dataArray.map(item => { return <ListItem lItem={item} /> }) // Generates the list also containing the checkboxes
</>
)
}
并且Checkbox
和PROCESS_COMPONENT
功能存在于单独的文件(Process.jsx
(中。
它看起来大致像:
import React, { useEffect, useState } from "react";
let ProcessSet = new Set(); // The globally declared set.
const CheckBox = ({lID}) => {
const [isTicked, setTicked] = useState(false);
const onTick = () => setTicked(!isTicked);
useEffect( () => {
if(isTicked) {
ProcessSet.add(lID);
}
else {
ProcessSet.delete(lID);
}
console.log(ProcessSet); // Checking for changes in set.
}, [isTicked]);
return (
<div onClick={onTick}>
//some content
</div>
)
}
const PROCESS_COMPONENT = () => {
const [len, setLen] = useState(ProcessSet.size);
useEffect( () => {
setLen(ProcessSet.size);
}, [ProcessSet]); // This change is never being picked up.
return (
<div>
<h6> {len} items checked </h6>
</div>
)
}
export { CheckBox, PROCESS_COMPONENT };
Set本身确实从Checkbox
中获得了正确的ID值。但PROCESS_COMPONENT
似乎没有接收到集合中的变化,len
显示0(集合的初始大小(。
我还没反应过来。但是,我们非常感谢您的帮助。
编辑:
基于@jdkramhoft的答案,我在Listings
函数中将该集设置为状态变量。
const ListItem = ({lItem,set,setPSet}) => {
//...
<CheckBox lID={lItem.id} pset={set} setPSet={setPSet} />
)
}
function Listings() {
const [processSet, setPSet] = useState(new Set());
//....
<PROCESS_COMPONENT set={processSet} />
dataArray.map(item => {
return <ListItem lItem={item} set={processSet} setPSet={setPSet} />
})
}
以及Process.jsx
的相应变化
const CheckBox = ({lID,pset,setPSet}) => {
//...
if (isTicked) {
setPSet(pset.add(lID));
}
else {
setPSet(pset.delete(lID));
}
//...
}
const PROCESS_COMPONENT = ({set}) => {
//...
setLen(set.size);
//...
}
现在,每当我点击复选框时,我都会收到一个错误:
TypeError: pset.add is not a function. (In 'pset.add(lID)', 'pset.add' is undefined)
删除函数也会出现类似的错误。
首先,如果您希望使用检测到的更改进行反应以正确地重新渲染,则该集应为反应状态const [mySet, setMySet] = useState(new Set());
。如果您需要该集可用于多个组件,您可以使用道具或上下文将其传递给它们。
其次,React检查像[ProcessSet]
这样的依赖关系是否已经用===
这样的东西改变了。即使集合中的项目不同,也不会检测到任何更改,因为对象是相同的,并且没有重新渲染。
更新:
[state, setState] = useState([]);
的setState
部分不是为了突变前一个状态,只是为了提供下一个状态。因此,要更新您的设置,您可以执行以下操作:
const [set, setSet] = useState(new Set())
const itemToAdd = ' ', itemToRemove = ' ';
setSet(prev => new Set([...prev, itemToAdd]));
setSet(prev => new Set([...prev].filter(item => item !== itemToRemove)));
正如您可能注意到的那样,这使得添加和删除集合的速度与列表一样慢。所以,除非你需要用set.has()
进行大量检查,否则我建议你使用一个列表:
const [items, setItems] = useState([])
const itemToAdd = ' ', itemToRemove = ' ';
setItems(prev => [...prev, itemToAdd]);
setItems(prev => prev.filter(item => item !== itemToRemove));