所以我在使用 react 钩子的过滤功能时遇到了问题,其中我有一组过滤器,其中包含与过滤器关联的标签。 用户单击过滤器,然后如果公司有与之关联的标签,则它只会显示这些过滤器。
现在,当他们单击过滤器时,我需要该过滤器进入数组,然后从该数组中我想进行公司过滤并设置公司 - 但是我收到一个错误,因为您无法在useEffect中设置公司。
在此示例中,将有一个带有标签节点的按钮 - 然后需要过滤所有具有与之关联的节点的公司。 如果他们取消单击过滤器,那么它需要显示所有过滤器,因此过滤器.length === 0 段代码。
您将如何正确设置它以使其不会出错?
const company = [{name:'google', tags:['javascript', 'node']}, {name:'facebook', tags:['javascript', 'ruby']}]
function App() {
const [filters, setFilter] = useState([])
const [companies, setCompanies] = useState(company)
useEffect(() => {
filterCompany()
}, [filters, companies]);
function addOrRemoveFilter(item) {
if (filters.includes(item)) {
const filteredItems = filters.filter(filteredItem => filteredItem !== item)
setFilter([...filteredItems])
} else {
setFilter([...filters, item])
}
}
function filterCompany() {
const res = companies.filter(company => {
return filters.every(filter => {
return company.tags.includes(filter)
})
})
const listOfCompanies = filters.length === 0 ? company : res
setCompanies([...listOfCompanies])
}
return (
<div className="App">
<div className="columns is-multiline filters is-centered">
{data.values.map((item, index) => (
<HomeFilters key={index} data={item} onFilterClick={(item) => addOrRemoveFilter(item)} />
))}
</div>
<div className="columns is-multiline is-centered ">
{companies.map((item, index) => (
<Companies key={index} data={item} />
))}
</div>
</div>
);
}
export default App;
如果要过滤数据,则可以创建另一个函数来获取过滤后的数据并使用它来呈现它。这样,您就不需要更新状态,当过滤器数组更改时,它将自动重新呈现。
例:
function getFilteredCompanies() {
const res = companies.filter(company => {
return filters.every(filter => {
return company.tags.includes(filter);
});
});
return filters.length === 0 ? company : res;
}
呈现:
{getFilteredCompanies().map((item, index) => <span key={index}>{item.name}</span>)}
您在声明之前调用filterCompany()
。
只需将此功能移到useEffect
上方
即可变换
useEffect(() => {
filterCompany()
}, [filters, companies]);
到
useEffect(() => {
filterCompany()
}, []);
使用useMemo
计算可导出数据,而不是在useState
中更新它:
const [filters, setFilter] = useState([])
function addOrRemoveFilter(item) {
if (filters.includes(item)) {
const filteredItems = filters.filter(filteredItem => filteredItem !== item)
setFilter([...filteredItems])
} else {
setFilter([...filters, item])
}
}
function filterCompany() {
const res = company.filter(comp => {
return filters.every(filter => {
return comp.tags.includes(filter)
})
})
return filters.length === 0 ? company : res
}
const companies = useMemo(() => filterCompany, [filters]);