In welchen Fällen würde das Ignorieren des Spread-Operators in useReducer zu Fehlern führen?

Nov 25 2020

In den meisten useReducerBeispielen, die ich gesehen habe, wurde der Spread-Operator verwendet, um Zustände zu erhalten. In all meinen Praktiken hat das Ignorieren jedoch nie Probleme verursacht. Es scheint, dass der Reduzierer in der Lage ist, den Zustand selbst ohne den Spread-Operator zu erhalten. Überprüfen Sie das folgende Beispiel:

const initialState = {
    color: 'black',
    bgColor: 'white'
}

const reducer = (state, action) => {
    switch (action.type) {
        case 'dawn':
            return {
                ...state,
                color: 'white',
                bgColor: 'purple'
            }
        case 'reset':
            return initialState
        default:
            return {
                state
            }
    }
}

const UseReducerColorSetter = () => {
    const [state, dispatch] = useReducer(reducer, initialState);
    const { color, bgColor } = state;
    return (
        <>
            <div style={{ color: `${color}`, backgroundColor: `${bgColor}` }} className='card'>
                Hello
            </div>
            <button onClick={() => dispatch({ type: 'dawn' })}>Dawn mode</button>
            <button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
        </>
    )
}

In diesem Beispiel verursacht das Entfernen ...statekeine Probleme, keine Statusänderung, keinen Konsolenfehler usw.

In dieser Frage habe ich gefragt: Ist es notwendig, den Spread-Operator in useReducer zu verwenden? Das Ignorieren des Spread-Operators verursachte Probleme in useState, aber immer noch keine Probleme mit useReducer.

Kann mir jemand einige Beispiele geben, wie ich den Spread-Operator ignorieren kann, der Probleme verursacht useReducer? Kann ein Reduzierer den Zustand bewahren?

Antworten

1 BrianThompson Nov 24 2020 at 23:53

Hier ist ein laufendes Beispiel, das zeigt, dass wenn Sie nicht alle Objekteigenschaften in einem Reduzierer ersetzen, diese verloren gehen. Vergleichen Sie die von der Konsole protokollierten Anfangswerte mit dem gedruckten Ergebnis.

const initialState = {
  color: "black",
  bgColor: "white"
};

const reducer = (state, action) => {
  switch (action.type) {
    case "dawn":
      return {
        bgColor: "purple" // Updated to only return one property to illustrate the problem
      };
    case "reset":
      return initialState;
    default:
      return {
        state
      };
  }
};

function App() {
  const [state, dispatch] = React.useReducer(reducer, initialState);

  React.useEffect(() => {
    console.log("Initial: ", state)
    dispatch({ type: "dawn" });
  }, []);

  return <div>{JSON.stringify(state)}</div>;
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Beachten Sie die Signatur der Reduzierfunktion (state, action) => newState . Diese Funktion gibt den neuen Status zurück. Was auch immer Sie returnvom Reduzierer sind, ist der neue Zustandswert in seiner Gesamtheit. Dies bedeutet, dass Sie ohne das Spreizen des Stammstatusobjekts alle Werte verlieren, die im neuen Objekt nicht explizit festgelegt wurden.

Wenn Sie Ihre Frage direkt beantworten, führt das Nichtverbreiten des vorherigen Status bei Reduzierungsaktualisierungen zu Fehlern, wenn Ihr Status ein Array oder Objekt ist, und Sie ersetzen nicht jeden Wert in dieser Struktur manuell.

Wenn Sie immer jede Objekteigenschaft festlegen oder den vorherigen Status zurückgeben, wird niemals ein Fehler auftreten. Dies ist das Szenario, das Sie in der Frage angegeben haben, und deshalb scheint es unnötig.

SergioVargas Nov 24 2020 at 23:28

In Ihrem speziellen Fall würde dies keine Auswirkungen haben oder Probleme verursachen, da Sie die Statuswerte (Farbe und bgColor) ändern. Wenn Sie beispielsweise nur die Farbe ändern, würde das Ignorieren des Spread-Operators den Status ohne einen bgColor-Wert belassen kann Probleme verursachen, wenn Ihre App jederzeit eine bgColor erwartet.

 case 'blue':
            return {
                color: 'blue',
            }