2016-09-26 3 views
2

Ich schreibe gerade eine React-Anwendung, wo ich auf den nächsten Kalendereintrag in meinem Redux-Zustand hören muss.Dispatch-Aktion für ein bestimmtes Datum-Zeit

Ich suche Beratung, wie dies am effektivsten zu tun und zu korrigieren.

Mein calendar Zustand Minderer besteht aus:

entries: [ 
    { 
     title: "Event 1", 
     start: "2016-09-26T08:00:00.000Z" 
     end: "2016-09-26T09:00:00.000Z" 
    }, 
    { 
     title: "Event 2", 
     start: "2016-09-26T10:00:00.000Z" 
     end: "2016-09-26T11:00:00.000Z" 
    }, 
    { 
     title: "Event 3", 
     start: "2016-09-26T13:00:00.000Z" 
     end: "2016-09-26T14:00:00.000Z" 
    } 
] 

Wenn das nächste Ereignis (Ereignis 1) passieren wird, würde Ich mag ein Ereignis versenden, den Zustand dieses Kalendereintrag zu handhaben. Die Einträge Reducer können jederzeit aktualisiert werden, so dass ich in der Lage sein muss, Einträge früher als der nächste Eintrag zu schieben.

Ich habe Redux und Redux Saga zur Verfügung für den Umgang damit.

Zeit mit einem Redux Saga Zuhörer wie ich arbeite:

export default function * watchCalendar() { 
    while (true) { 
     const entry = yield select((state) => state.calendar.entries[0]); 
     if (entry) { 
      const now = moment().startOf("minute"); 
      const start = moment(entry.start); 
      if (now.isAfter(start)) { 
       put(CalendarActions.setActiveEntry(entry)); 
      } 
     } 
    } 
} 

Aber nicht wie erwartet funktioniert, wie die while wird nach dem ersten Versuch zu beenden. Ich muss es weiter auf den Staat hören lassen. Das oben genannte ist nicht wirklich so effektiv, wie ich es gerne hätte.

Alle Ratschläge, Ideen oder Codebeispiele sind willkommen.

UPDATE 1, 2, 3, 4

ich ein bisschen bin immer noch Hacking, ein Stück näher:

export function * watchNextCalendarEntry() { 
    while (true) { // eslint-disable-line no-constant-condition 
     const next = yield select((state) => CalendarSelectors.getNextEntry(state.calendar)); 
     if (next) { 
      const start = moment(next.start); 
      const seconds = yield call(timeleft, start); 

      yield call(delay, seconds * 1000); 
      yield put(CalendarActions.setActiveCalendarEntry(next)); 
     } 
    } 
} 

function * currentCalendarEntry(action) { 
    try { 
     while (true) { // eslint-disable-line no-constant-condition 
      const entry = action.payload; 
      const end = moment(entry.end); 
      const seconds = yield call(timeleft, end); 

      yield call(delay, seconds * 1000); 
      yield put(CalendarActions.setInactiveCalendarEntry(entry)); 
     } 
    } 
    finally { 
     if (yield cancelled()) { 
      // e.g. do something 
     } 

    } 
} 

export function * watchCurrentCalendarEntry() { 
    while (true) { // eslint-disable-line no-constant-condition 
     const action = yield take(ActionTypes.SET_ACTIVE_CALENDAR_ENTRY); 
     const watcher = yield fork(currentCalendarEntry, action); 

     yield take(ActionTypes.SET_INACTIVE_CALENDAR_ENTRY); 
     yield cancel(watcher); 
    } 
} 

function getTimeLeft(date) { 
    return date.diff(moment().startOf("second"), "seconds"); 
} 

Antwort

0

So etwas wie das?

export default function* watchNextCalendarEntry() { 
    takeLatest(SUBSCRIBE_CALENDAR_ENTRY, subscribeCalendarEntry); 
} 

function* subscribeCalendarEntry({ nextEntry }) { 
    const timeLeft = moment(nextEntry.start).diff(moment()); 

    yield call(delay, timeLeft); 

    yield put(CalendarActions.setActiveCalendarEntry(nextEntry)); 
} 

Sie müßten { type: SUBSCRIBE_CALENDAR_ENTRY, nextEntry } Aktion beim Start der App und wenn Eintrag Änderungen dann berechnen und in nextEntry an die Aktion übergeben versenden.

+0

Gute Idee beim Abonnieren des nächsten Eintrags - wenn also ein anderer Eintrag kommt, zählen wir dazu. Stellen Sie nur sicher, dass der "nächste" Eintrag auch der nächste Eintrag in der Zeit ist. – janhartmann

+0

Ja, also nextEntry muss der nächste Eintrag sein. Wenn das Sinn macht, können Sie dies in der Sage berechnen, müssen aber den 'Select'-Effekt verwenden – yjcxy12

Verwandte Themen