简体   繁体   English

state 在使用中不清除效果

[英]state doesn't clear in useEffect

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.这行得通,但我不明白为什么setAllEvents([])不清除我的事件数组。 Instead new array is joins with old one and I get duplicate of some elements.相反,新数组与旧数组连接,我得到一些元素的重复。

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 ...;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM