Richtige Art der Fehlerbehandlung in React-Redux

11

Ich möchte verstehen, was eine allgemeinere oder korrektere Art der Fehlerbehandlung mit React-Redux ist.

Angenommen, ich habe eine Telefonnummer-Anmeldekomponente.

Diese Komponente gibt einen Fehler aus, wenn die eingegebene Telefonnummer ungültig ist

Was wäre der beste Weg, um diesen Fehler zu behandeln?

Idee 1: Erstellen Sie eine Komponente, die einen Fehler aufnimmt und eine Aktion auslöst, wenn ein Fehler an sie übergeben wird

Idee 2: Da der Fehler mit dieser Komponente zusammenhängt, übergeben Sie diesen Fehler an eine Komponente (die nicht mit Redux verbunden ist, dh die Fehlerbehandlungskomponente löst die Aktion nicht aus).

Frage: Kann mich jemand zur richtigen Art der Fehlerbehandlung in React-Redux für große Apps führen?

anny123
quelle
1
Wie erfolgt die Überprüfung der Telefonnummer synchron oder asynchron, nachdem der Benutzer etwas oder sofort getan hat? Was möchten Sie passieren, sichtbar für den Benutzer? Redux dient zum Speichern des Status Ihrer App. Es scheint etwas unabhängig von Ihrer Frage zu sein.
RemcoGerlich

Antworten:

3

Ich würde sagen, dass keine Ihrer ersten Ideen das ganze Bild erfasst. Idee 1 ist nur ein Rückruf. Wenn Sie einen Rückruf verwenden möchten : useCallback. Idee 2 funktioniert und ist vorzuziehen, wenn Sie keinen Redux verwenden müssen. Manchmal ist es besser, Redux zu verwenden. Möglicherweise legen Sie die Gültigkeit des Formulars fest, indem Sie überprüfen, ob keines der Eingabefelder Fehler oder ähnliches aufweist. Da wir uns mit Redux befassen, nehmen wir an, dass dies der Fall ist.

Normalerweise besteht der beste Ansatz zur Fehlerbehandlung mit Redux darin, ein Fehlerfeld im Status zu haben, das dann an eine Fehlerkomponente übergeben wird.

const ExampleErrorComponent= () => {
  const error = useSelector(selectError);
  if (!error) return null;
  return <div className="error-message">{error}</div>;
}

Die Fehlerkomponente muss nicht nur einen Fehler anzeigen, sondern kann auch Nebenwirkungen verursachen useEffect.

Wie der Fehler gesetzt / deaktiviert wird, hängt von Ihrer Anwendung ab. Verwenden wir ein Beispiel für Ihre Telefonnummer.

1. Wenn die Gültigkeitsprüfung eine reine Funktion ist, kann sie im Reduzierer durchgeführt werden.

Sie würden dann das Fehlerfeld als Reaktion auf Aktionen zum Ändern der Telefonnummer setzen oder deaktivieren. In einem Reduzierer, der mit einer switch-Anweisung erstellt wurde, könnte dies so aussehen.

case 'PHONE_NUMBER_CHANGE':
  return {
    ...state,
    phoneNumber: action.phoneNumber,
    error: isValidPhoneNumber(action.phoneNumber) ? undefined : 'Invalid phone number',
  };

2. Wenn das Backend Fehler meldet, lösen Sie Fehleraktionen aus.

Angenommen, Sie senden die Telefonnummer an ein Backend, das die Validierung durchführt, bevor es etwas mit der Nummer macht. Sie können nicht wissen, ob die Daten auf der Clientseite gültig sind. Sie müssen nur das Wort des Servers dafür nehmen.

const handleSubmit = useCallback(
  () => sendPhoneNumber(phoneNumber)
    .then(response => dispatch({
      type: 'PHONE_NUMBER_SUBMISSION_SUCCESS',
      response,
    }))
    .catch(error => dispatch({
      type: 'PHONE_NUMBER_SUBMISSION_FAILURE',
      error,
    })),
  [dispatch, phoneNumber],
);

Der Reduzierer sollte dann eine entsprechende Meldung für den Fehler erstellen und einstellen.

Vergessen Sie nicht, den Fehler zu deaktivieren. Sie können den Fehler je nach Anwendung bei einer Änderungsaktion oder bei einer anderen Anforderung deaktivieren.

Die beiden von mir skizzierten Ansätze schließen sich nicht gegenseitig aus. Sie können die erste verwenden, um lokal erkennbare Fehler anzuzeigen, und die zweite verwenden, um serverseitige oder Netzwerkfehler anzuzeigen.

Jemi Salo
quelle
Ich schätze Ihre Antwort sehr und dies sieht definitiv besser aus als das, was ich tue. Ich bin noch auf der Suche nach weiteren Vorschlägen und habe daher eine Prämie für diese Frage gestartet.
anny123
1

Ich würde ein Formular mit Yup-Validierung verwenden. dann würde ich für serverseitige Fehler so etwas verwenden:

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Spinner } from "@blueprintjs/core";

export default ({ action, selector, component, errorComponent }) => {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(action());
  }, [dispatch, action]);

  const DispatchFetch = () => {
    const { data, isRequesting, error } = useSelector(selector());
    if (!isRequesting && data) {
      const Comp = component;
      return <Comp data={data}></Comp>;
    } else if (error) {
      if (errorComponent) {
        const ErrorComp = errorComponent;
        return <ErrorComp error={error}></ErrorComp>;
      }
      return <div>{error}</div>;
    }
    return <Spinner></Spinner>;
  };

  return <DispatchFetch></DispatchFetch>;
};
anerco
quelle
Sieht interessant aus anerco, Danke für die Antwort :)
anny123
1

Es hängt davon ab, um welche Art von Fehlerbehandlung es sich handelt. Wenn es sich nur um die Handhabung der Formularvalidierung handelt, brauchen Sie dafür wahrscheinlich kein Redux - bitte lesen Sie diesen Artikel . Wenn Ihr Fehler nur innerhalb dieser Komponente "verbraucht" wird, warum ihn an redux senden? Sie können dafür einfach Ihren lokalen Staat verwenden.

Wenn Sie dem Benutzer andererseits eine Fehlerbenachrichtigung anzeigen möchten, die angibt, ob ein HTTP-Aufruf vor Ort fehlgeschlagen ist, können Sie von Redux profitieren, indem Sie Fehler von allen Teilen Ihrer Anwendung (oder sogar generisch von Ihrer Middleware) auslösen.

dispatch({ type: 'SET_ERROR_MESSAGE', error: yourErrorOrMessage });

// simple error message reducer
function errorMessage(state = null, action) {
  const { type, error } = action;

  switch (type) {
      case 'RESET_ERROR_MESSAGE':
          return null;
      case 'SET_ERROR_MESSAGE':
          return error;
  }

  return state
}

Sie müssen definieren, wie Ihr Status organisiert werden soll und ob Sie einen Status in Redux setzen oder ihn einfach im lokalen Status Ihrer Komponente belassen müssen. Sie könnten alles in Redux setzen, aber persönlich würde ich sagen, dass es ein Overkill ist - warum sollten Sie Zustand X in Komponente Y setzen, wenn sich nur Komponente Y um diesen Zustand kümmert? Wenn Sie Ihren Code richtig strukturieren, sollten Sie später kein Problem damit haben, diesen Status von lokal auf redux zu verschieben, wenn aus irgendeinem Grund andere Teile Ihrer App von diesem Status abhängen.

zhuber
quelle
1

Ich denke so darüber nach, was sollte Zustand sein? Und was soll vom Staat abgeleitet werden? Der Zustand sollte in Redux gespeichert und Ableitungen berechnet werden.

Eine Telefonnummer ist state, welches Feld den Fokus hat, ist state, aber ob es gültig ist oder nicht, kann aus den Werten in state abgeleitet werden.

Ich würde Reselect verwenden, um Ableitungen zwischenzuspeichern und dieselben Ergebnisse zurückzugeben, wenn der relevante Status nicht geändert wurde.

export const showInvalidPhoneNumberMessage = createSelector(
  getPhoneValue,
  getFocusedField,
  (val, focus) => focus !== 'phone' && val.length < 10 // add other validations.
)

Sie können den Selektor in mapStateToProps dann in allen Komponenten verwenden, die diesen Wert möglicherweise interessieren, und Sie können ihn auch in asynchronen Aktionen verwenden. Wenn sich der Fokus nicht geändert hat oder sich der Wert des Feldes nicht geändert hat, erfolgt keine Neuberechnung. Stattdessen wird der vorherige Wert zurückgegeben.

Ich füge die ausgewählte Statusprüfung hinzu, um zu zeigen, wie mehrere Statuselemente zusammenkommen können, um eine Ableitung zu erhalten.

Ich persönlich versuche, Dinge anzugehen, indem ich meinen Zustand so klein wie möglich halte. Angenommen, Sie möchten einen eigenen Kalender erstellen. Speichern Sie jeden einzelnen Tag im Bundesstaat oder müssen Sie nur ein paar Dinge wissen, z. B. das aktuelle Jahr und den aktuellen Monat, die gerade angezeigt werden. Mit nur diesen beiden Statuselementen können Sie die Tage berechnen, die in einem Kalender angezeigt werden sollen, und müssen nicht neu berechnen, bis sich einer von ihnen ändert. Diese Neuberechnung erfolgt praktisch automatisch, ohne über alle möglichen Möglichkeiten nachdenken zu müssen Veränderung.

sattes Grün
quelle