reactjs 为什么它只显示一个集合从CloudFirestore?

mwkjh3gx  于 2023-03-17  发布在  React
关注(0)|答案(1)|浏览(135)

我正在使用react,redux,firebase和react big日历创建一个日历。在主页上,我有两个相同的日历,但每个日历都连接到firebase中不同的集合。如果我单独使用它们,它可以让我发布,删除,更新和查看事件,但当我把两个日历放在一起时,我只能与一个集合交互。
截图:

我认为问题是在状态中,因为当我刷新页面时,在redux扩展中首先出现第一个日历的事件,然后是第二个日历的事件.如果这是问题,我怎么能解决它?我想类似于将日历的事件合并到状态中,但我不知道这是否会使相同的事件再次出现在2个日历中
我希望有人能帮助我
谢谢!
图形接口:https://github.com/guidomora/peluqueria-new-calendar/tree/main/src
部署:https://peluqueria-new-calendar.vercel.app/
还原扩展名:

calendarSlice.js:

initialState: {
    events: [],
    activeEvent: null,
    isLoadingEvents: true,
  },

  reducers: {
    onSetActiveEvent: (state, { payload }) => {
      state.activeEvent = payload;
    },
    onAddEvent: (state, { payload }) => {
      state.events.push(payload);
      state.activeEvent = null;
    },
    onUpdateEvent: (state, { payload }) => {
      state.events = state.events.map((event) => {
        if (event.id === payload.id) {
          return payload;
        }
        return event;
      });
    },
    setEvent: (state, { payload }) => {
      state.events = payload;
    },

使用自定义钩子从firebase获取事件的代码:我使用${nombre}来更改每个组件中集合的名称只是字符串
使用日历存储:

const startLoadingEvents = async () => {
    const querySnapshot = await getDocs(collection(db, `${nombre}`));
    const events = [];
    querySnapshot.forEach((doc) => {
      events.push({
        id: doc.id,
        start: doc.data().start.toDate(),
        end: doc.data().end.toDate(),
        title: doc.data().title,
        notes: doc.data().notes,
      });
    });
    dispatch(setEvent(events));
  };
ckx4rj1h

ckx4rj1h1#

看起来问题是calendarSlice只为一个日历保存events状态,每次setEvent操作被调度时,它只会替换state.calendar.events,以前存在的任何内容都会被覆盖。
从你的描述中听起来,你需要多个events数组,每个数组对应一个你要查询的日历集合。你可以更新calendarSlice来保存多个日历事件数组。我猜这个集合id nombre足以区分/标识一个唯一日历的事件状态。
建议的重构示例:

const startLoadingEvents = async () => {
  const querySnapshot = await getDocs(collection(db, `${nombre}`));
  const events = [];
  querySnapshot.forEach((doc) => {
    events.push({
      id: doc.id,
      start: doc.data().start.toDate(),
      end: doc.data().end.toDate(),
      title: doc.data().title,
      notes: doc.data().notes,
    });
  });
  dispatch(setEvent({ calendarId: nombre, events }));
};
export const calendarSlice = createSlice({
  name: "calendar",
  initialState: {
    events: {}, // <-- { [nombre]: event[] }
    activeEvent: null,
    isLoadingEvents: true,
  },
  reducers: {
    onSetActiveEvent: (state, { payload }) => {
      state.activeEvent = payload;
    },
    onAddEvent: (state, { payload }) => {
      if (!state.events[payload.calendarId]) {
        state.events[payload.calendarId] = [];
      }
      state.events[payload.calendarId].push(payload.event);
      state.activeEvent = null;
    },
    onUpdateEvent: (state, { payload }) => {
      state.events[payload.calendarId] = state.events[payload.calendarId].map(
        (event) => event.id === payload.event.id) ? payload : event
      );
    },
    onDeleteEvent: (state) => {
      if (state.activeEvent?.calendarId) {
        state.events[state.activeEvent.calendarId] = state.events[state.activeEvent.calendarId]
          .filter((event) => event._id !== state.activeEvent._id);
        state.activeEvent = null;
      }
    },
    setEvent: (state, { payload }) => {
      state.events[payload.calendarId] = payload.events;
    },
    onLoadEvents: (state, { payload }) => {
      state.isLoadingEvents = false;

      (payload.events || []).forEach((event) => {
        const exists = state.events[payload.calendarId]?.some(
          (dbEvent) => dbEvent.id === event.id
        );
        if (!exists) {
          state.events[payload.calendarId].push(event);
        }
      });
    },
  },
});

选择状态时,需要更新以将state.calendar.events作为对象而不是数组使用。

const calendars = useSelector(state => state.calendar.events); // { [nombre]: event[] }

...

calendars[<name of collection>].map(event => { .... })

显然,这一切都没有经过测试,因为我没有访问您的firebase后端,也没有站起来任何运行代码的andbox,但它应该是一个很好的一般开始处理多个日历集合的数据在UI中。

相关问题