Reactjs 基于道具的UseEffect正在向状态数组添加副本
所以,请简要描述一下这个问题 用户可以通过Reactjs 基于道具的UseEffect正在向状态数组添加副本,reactjs,react-hooks,react-state,Reactjs,React Hooks,React State,所以,请简要描述一下这个问题 用户可以通过html选择标记选择半径,该值作为道具发送到此组件,如果该值更改useffect重新渲染器 我现在实现它的方式产生了一个问题,过滤事件被添加到状态。因此它不断地向数组中添加重复项 如何使用useffect/setState确保删除或覆盖以前的项目,并且在状态中只存储唯一的事件 const [data, setData] = useState(); const [userLat, setUserLat] = useState(); const [userL
html选择标记
选择半径,该值作为道具
发送到此组件,如果该值更改useffect
重新渲染器
我现在实现它的方式产生了一个问题,过滤事件
被添加到状态
。因此它不断地向数组中添加重复项
如何使用useffect/setState
确保删除或覆盖以前的项目,并且在状态中只存储唯一的事件
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]);
const[data,setData]=useState();
const[userLat,setUserLat]=useState();
const[userLon,setUserLon]=useState();
const[evtsFiltered,setEvtsFiltered]=useState([]);
//获取所有事件并以状态存储
useffect(()=>{
axios.get(“http://localhost:5000/events)然后((res)=>{
setData(res.data.events);
});
}, []);
//根据用户的位置筛选事件
useffect(()=>{
数据?.forEach((el)=>{
Geocode.fromAddress(`${el.address}`)
。然后((res)=>{
让dis=获得精确距离(
{
纬度:parseFloat(res.results[0].geometry.location.lat),
经度:parseFloat(res.results[0].geometry.location.lng),
},
{纬度:parseFloat(userLat),经度:parseFloat(userLon)}
);
如果(dis/1000[…evtsFiltered,el]);
}
})
.catch((err)=>console.log(err));
});
},[data,userLon,userLat,props.radius];
我知道行setEvtsFiltered((evtsFiltered)=>[…evtsFiltered,el])
是错误的,因为我使用spread操作符将新事件与以前的事件一起存储。
问题是我不知道如何修复它
如果有人能给我指出正确的方向
提前谢谢 我会将数据映射到承诺数组,并等待所有承诺都使用
Promise.all()
,然后用新数组替换当前状态。要删除与条件不匹配的项,可以返回一个空数组,然后使用array.flat()
将结果展平以删除它们
示例(未测试):
useffect(async()=>{
试一试{
const evts=等待承诺。全部(
data.map(异步(el)=>{
const res=wait Geocode.fromAddress(`${el.address}`);
让dis=获得精确距离({
纬度:parseFloat(res.results[0].geometry.location.lat),
经度:parseFloat(res.results[0].geometry.location.lng),
}, {
纬度:parseFloat(userLat),
经度:parseFloat(userLon)
});
return dis/1000这是一个很好的干净解决方案,尽管我更喜欢。我真的不明白为什么人们会如此回避它。非常感谢Ori Drori,它的工作方式很有魅力!@trixn你能不能也给我一个使用reduce的解决方案?@trixn从一个数组减少到一个数组没有那么惯用,我们有这方面的地图。
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]);