Bernd das Brot: React-SPA: best practice, um mit Aktionen nach einer Action umzugehen?

Beitrag lesen

Würdest rethrows empfehlen?

Ja, das ist das Standardvorgehen beim Arbeiten mit Promises, also mache ich es auch im Zusammenhang mit redux-thunk.

Dieses "Rethrowing" kann man natürlich kapseln, sodass man es nicht ausdrücklich schreiben muss und nicht vergessen kann. Wie würdest du das implementieren?

Ich habe eine Helferfunktion, um Requests zu machen:

const cancelledError = throw new Error('Cancelled request');

function request(options) {
  return (dispatch, getState) => {
    let cancelled = false;
    const promise = axios({
      method: options.method,
      url: options.url,
      data: options.body,
      headers:
        options.authenticated ?
        { 'X-Access-Token': getState().session.token } :
        {}
    });
    promise.cancel = () => {
      cancelled = true;
    };
    dispatch(options.pendingAction(promise));
    return promise.then(
      (result) => {
        if (cancelled) {
          throw cancelledError;
        }
        dispatch(options.successAction(result));
        return result;
      },
      (error) => {
        if (cancelled) {
          throw cancelledError;
        }
        dispatch(options.errorAction(result));
        throw error;
      },
    );
  };
}

Dann:

function createFoo(foo) {
  return function(dispatch) {
    return dispatch(
      request({
        method: 'POST',
        url: '/foos',
        body: foo,
        authenticated: true,
        pendingAction: createFooPending,
        successAction: createFooSuccess,
        errorAction: createFooError,
      })
    );
  };
}

(ungetestet, soll nur das Prinzip )

Wie gehst du denn damit um, dass man ggfls Requests canceln will, etwa weil der User wild herumklickt und damit mehrere Actions auf einmal auslöst?

Dafür habe ich eine Lösung gefunden, aber keine schöne.

Ich habe einen "cancelable promise" gebaut (siehe oben - da gibts auch bessere Lösungen). Dieser wird als Payload einer Pending-Action dispatcht. Der Reducer speichert ihn dann im Redux-Store. Beim nächsten Aufruf des Action Creators wird der laufende Promise mit getState() aus dem Store geholt. Gibt es einen, so wird er mit .cancel() abgebrochen. Bei Success oder Error wird der Promise aus dem Store entfernt.

Du meinst, dass ich den Action Creator weiter zerlege in kleinere, die nacheinander dispatcht werden und die Komponente dann nur den „Haupt-Action-Creator“ bekommt?

Genau!

Bernd das Brot