我正在使用useEffect从API检索一些数据,我希望能够使用从其父组件馈送到组件中的道具来过滤返回的数据。
我试图在useEffect设置状态后对其进行过滤,但看起来组件将进入无限渲染循环。
我需要做些什么来防止这种情况发生?
export default function HomeJobList(props: Props): ReactElement {
const [listings, setListings] = React.useState(null);
useEffect(() => {
const func = async () => {
let res = await service.getListings();
setListings(res);
};
func();
}, []);
if (props.searchTerm && listings) {
let filtered = listings.filter((x) => x.positionTitle.includes(props.searchTerm));
setListings(filtered);
}
return (
<>
<div>do stuff</div>
</>
);
}
我知道,使用setListing函数会在过滤后导致一个reender,然后导致另一个setListing调用。但打破这种循环的最佳方法是什么?
我应该只使用另一个状态值来维护上次用于筛选的searchTerm,并在筛选之前对此进行检查吗?
或者有更好的方法吗?
这是一个独立循环,因为每次过滤时,都将其设置为状态变量,从而导致重新渲染和过滤&再次设置变量-因此是一个循环。
我建议你在一个地方完成所有操作(你的useEffect
是一个很好的地方,因为它只执行一次
useEffect(() => {
(async () => {
const res = await service.getListings();
const filtered = res.filter((x) => x.positionTitle.includes(props.searchTerm));
setListings(filtered);
})();
}, []);
当状态发生变化,触发重新渲染时,这就是为什么会有一个无限循环;你要做的是将你的过滤包装在一个useEffect中,这个useEffect依赖于searchTerm
道具,比如:
import React, { useEffect } from 'react';
export default function HomeJobList() {
const [listings, setListings] = React.useState(null);
useEffect(() => {
const func = async () => {
let res = await service.getListings();
setListings(res);
};
func();
}, []);
useEffect(() => {
if (listings) {
let filtered = listings.filter(x =>
x.positionTitle.includes(props.searchTerm)
);
setListings(filtered);
}
}, [props.searchTerm]);
return (
<>
<div>do stuff</div>
</>
);
}
您需要创建一个在返回的JSX内部调用的函数。
实际上,每次Props
对象更改时,都需要渲染组件。这是通过调用JSX代码中的函数来实现的。
示例:
功能:
const filteredListings = () => {
if (props.searchTerm && listings) {
let filtered = listings.filter((x) => {
x.positionTitle.includes(props.searchTerm));
}
return filtered;
}
}
退货声明:
return (
<ul>
{
filteredListings().map((listing) =>
<li>{listing.title}</li>
);
}
</ul>
);
您需要的是一个useEffect
,它在道具更改时进行过滤。
更换此
if (props.searchTerm && listings) {
let filtered = listings.filter((x) => x.positionTitle.includes(props.searchTerm));
setListings(filtered);
}
带有
useEffect(()=>{
if (props.searchTerm) {
setListings(prevListing => {
return prevListing.filter((x) => x.positionTitle.includes(props.searchTerm))
});
}
}, [props.searchTerm] )