如何解决基于 props 的 UseEffect 向状态数组添加重复项
问题的简短描述
用户可以通过 html select tag
选择半径,此值作为 prop
发送到此组件,如果该值更改 useEffect
重新渲染
按照我现在的实施方式,它产生了将 filtered events
添加到 state
的问题。所以它不断向数组添加重复项。
我如何使用 useEffect / setState
来确保之前的项目将被删除或覆盖,并且只有唯一的事件存储在 state
中?
const [data,setData] = useState();
const [userLat,setUserLat] = useState();
const [userLon,setUserLon] = useState();
const [evtsFiltered,setEvtsFiltered] = useState([]);
// Fetch all events and store in state
useEffect(() => {
axios.get("http://localhost:5000/events").then((res) => {
setData(res.data.events);
});
},[]);
// Filter events based on user's location
useEffect(() => {
data?.forEach((el) => {
Geocode.fromAddress(`${el.address}`)
.then((res) => {
let dis = getPrecisedistance(
{
latitude: parseFloat(res.results[0].geometry.location.lat),longitude: parseFloat(res.results[0].geometry.location.lng),},{ latitude: parseFloat(userLat),longitude: parseFloat(userLon) }
);
if (dis / 1000 <= props.radius) { // props.radius will trigger the useEffect when user selects a new value on the homepage
setEvtsFiltered((evtsFiltered) => [...evtsFiltered,el]);
}
})
.catch((err) => console.log(err));
});
},[data,userLon,userLat,props.radius]);
我知道 setEvtsFiltered((evtsFiltered) => [...evtsFiltered,el])
行是错误的,因为我使用 spread operator.
将新事件与以前的事件存储在一起,问题是我不知道如何修复它。
如果有人能指出我正确的方向?
提前致谢!
解决方法
我会将数据映射到一个 Promise 数组,并在使用新数组替换当前状态之前等待所有这些使用 Promise.all()
完成。要删除不符合条件的项目,您可以返回一个空数组,然后使用 Array.flat()
将结果展平以删除它们
示例(未测试):
useEffect(async() => {
try {
const evts = await Promise.all(
data.map(async(el) => {
const res = await Geocode.fromAddress(`${el.address}`);
let dis = getPreciseDistance({
latitude: parseFloat(res.results[0].geometry.location.lat),longitude: parseFloat(res.results[0].geometry.location.lng),},{
latitude: parseFloat(userLat),longitude: parseFloat(userLon)
});
return dis / 1000 <= props.radius ? el : [];
})
);
setEvtsFiltered(evts.flat());
} catch (e) {
console.log(err);
}
},[data,userLon,userLat,props.radius]);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。