Reputation: 333
I wanted to re-render my component and update array of events when filters are changing.
const filters = useSelector(state => state.mapRedux.filters)
const [allEvents, setAllEvents] = useState([]);
const getAllEvents = async (start) => {
let myEventsArray = [];
await firebase.firestore().collection('wydarzenie')
.where('sport', 'in', createFiltersTable())
.where('miasto', '==', currentCity)
.orderBy("data_rozpoczecia")
.startAfter(start)
.limit(limit)
.get().then(snapshot => {
if (snapshot.size < limit) setShowMore(false)
snapshot.forEach(doc => {
let info = doc.data()
let el = {
id: doc.id,
...info
}
myEventsArray.push(el)
});
})
let new_array = allEvents.concat(myEventsArray)
setAllEvents(new_array);
}
useEffect(() => {
setAllEvents([])
getAllEvents(new Date());
}, [filters])
And that works, but I don't why setAllEvents([])
doesn't clear my events array. Instead new array is joins with old one and I get duplicate of some elements.
Upvotes: 1
Views: 629
Reputation: 39280
Here is what you can do to prevent stale closures but not run the effect too many times:
const AllEvents = (props) => {
const currentCity = useSelector(
(state) => state.mapRedux.city.name
);
const [allEvents, setAllEvents] = useState([]);
const [limit, setLimit] = useState(6);
const [showMore, setShowMore] = useState(true);
// filtry
const filters = useSelector(
(state) => state.mapRedux.filters
);
const createFiltersTable = React.useCallback(() => {
const tmp = Object.values(filters);
const values = [];
tmp.map((el) => {
if (el.active) values.push(el.events_name);
});
return values;
}, [filters]); //re create this function when filters change
const getAllEvents = React.useCallback(
async (start) => {
let myEventsArray = [];
await firebase
.firestore()
.collection('wydarzenie')
.where('sport', 'in', createFiltersTable())
.where('miasto', '==', currentCity)
.orderBy('data_rozpoczecia')
.startAfter(start)
.limit(limit)
.get()
.then((snapshot) => {
if (snapshot.size < limit) setShowMore(false);
snapshot.forEach((doc) => {
let info = doc.data();
let el = {
id: doc.id,
...info,
};
myEventsArray.push(el);
});
});
setAllEvents((allEvents) =>
//use callback to prevent allEvents being a dependency
allEvents.concat(myEventsArray)
);
},
//re create getAllEvents when createFiltersTable, currentCity
// or limit changes
[createFiltersTable, currentCity, limit]
);
useEffect(() => {
setAllEvents([]);
getAllEvents(new Date());
//effect will run when filters change or when
// getAllEvents change, getAllEvents will change
// when filters, currentCity or limit changes
}, [filters, getAllEvents]);
return ...;
};
Upvotes: 1