Heim > Web-Frontend > js-Tutorial > Hauptteil

useReducer und wie es sich von useState unterscheidet

Susan Sarandon
Freigeben: 2024-10-30 20:04:30
Original
682 Leute haben es durchsucht

useReducer and how it is different from useState

Inhaltsverzeichnis

  1. Einführung
  2. Wann sollte useState verwendet werden?
  3. Wann sollte useReducer verwendet werden?
  4. Beispiel 1: Zähler-App mit useState
  5. Beispiel 2: Counter-App mit useReducer
  6. Beispiel 3: Formulareingabeverarbeitung mit useReducer
  7. Beispiel 4: Erstellen einer Quiz-App mit useReducer
  8. Vergleich zwischen useState und useReducer
  9. Fazit

Einführung

React bietet zwei wichtige Hooks zum Verwalten des Status: useState und useReducer. Obwohl beide für die Zustandsverwaltung in Funktionskomponenten konzipiert sind, werden sie in unterschiedlichen Szenarien verwendet. In diesem Artikel werden die Unterschiede zwischen den beiden erläutert und hervorgehoben, wann Sie beide verwenden sollten, mit Beispielen zum besseren Verständnis

Wann sollte useState verwendet werden?

useState ist ein einfacher und effektiver Hook für die Handhabung des lokalen Status, wenn:

  • Sie müssen einen einfachen Status verwalten (wie boolesche Werte, Zahlen oder Zeichenfolgen).
  • Sie möchten, dass der Status mit minimalem Aufwand direkt aktualisiert wird.
  • Der Zustand weist keine komplexen Übergänge oder Abhängigkeiten von mehreren Variablen auf.

Grundlegende Syntax

const [state, setState] = useState(initialState);
Nach dem Login kopieren
Nach dem Login kopieren
  • Status: Der aktuelle Status.
  • setState: Eine Funktion zum Aktualisieren des Status.
  • initialState:Der Anfangszustand

Wann sollte useReducer verwendet werden?

useReducer ist nützlich, wenn:

  • Sie haben eine komplexe Zustandslogik.
  • Mehrere Statusaktualisierungen hängen voneinander ab.

Grundlegende Syntax

const [state, dispatch] = useReducer(reducer, initialState);

Nach dem Login kopieren
Nach dem Login kopieren
  • Status: Der aktuelle Status.
  • Dispatch: Eine Funktion zum Senden einer Aktion an den Reduzierer, um eine Statusaktualisierung auszulösen.
  • Reduzierer: Ein Reduzierer ist eine reine Funktion, die zwei Argumente benötigt: den aktuellen Zustand und eine Aktion. Es gibt den neuen Status basierend auf der Aktion zurück.

Grundlegende Syntax

const reducer = (state, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { count: state.count + 1 };
        case 'DECREMENT':
            return { count: state.count - 1 };
        default:
            return state;
    }
}
Nach dem Login kopieren
Nach dem Login kopieren
  • Aktion: Eine Aktion ist ein Objekt, das beschreibt, welche Änderung stattfinden soll
    Es verfügt normalerweise über eine type-Eigenschaft und optional eine payload.
    Der Typ teilt dem Reduzierer mit, welche Art von Zustandsänderung vorgenommen werden soll.
    Die Nutzlast enthält alle zusätzlichen Daten, die für die Änderung benötigt werden.

  • InitialState:Der Anfangszustand, genau wie der Anfangszustand in useState.

Beispiel 1 Zähler-App mit useState

const [state, setState] = useState(initialState);
Nach dem Login kopieren
Nach dem Login kopieren

Erläuterung

  • Wir verwenden useState, um den Zählwert zu verfolgen.
  • Wir haben zwei Schaltflächen: eine zum Erhöhen und eine zum Verringern des Zählstands.
  • Der Status wird direkt mit der setCount-Funktion aktualisiert.

Beispiel 2: Counter-App mit useReducer

const [state, dispatch] = useReducer(reducer, initialState);

Nach dem Login kopieren
Nach dem Login kopieren

Erläuterung

  • Die Reduzierfunktion steuert, wie sich der Status basierend auf der ausgelösten Aktion ändern soll.
  • Anstatt den Status direkt festzulegen, senden wir Aktionen (Inkrementieren, Dekrementieren), um Änderungen auszulösen.

Beispiel 3: Formulareingabeverarbeitung mit useReducer

Erweitern wir das Konzept auf die Handhabung eines Formulars mit mehreren Eingabefeldern. Dieses Szenario ist ideal für useReducer, da es mehrere Statuseigenschaften basierend auf Aktionen aktualisiert.

const reducer = (state, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { count: state.count + 1 };
        case 'DECREMENT':
            return { count: state.count - 1 };
        default:
            return state;
    }
}
Nach dem Login kopieren
Nach dem Login kopieren

Erläuterung

  • Der Reduzierer verwaltet den Formularstatus, indem er verschiedene Eigenschaften (Name, E-Mail) basierend auf dem Typ der Aktion aktualisiert.
  • Dispatch sendet die Aktion an den Reduzierer, um den Status zu aktualisieren. Die Nutzlast trägt die Daten (z. B. den Eingabewert).

Beispiel 4: Erstellen einer Quiz-App mit useReducer

Hinweis: Das Styling wurde mit tailwindcss durchgeführt

import React, { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
}


Nach dem Login kopieren

Erläuterung

*Ausgangszustand mit useReducer

import React, { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

export default function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}

Nach dem Login kopieren
  • Reduzierfunktion
import React, { useReducer } from 'react';

const initialState = {
  name: '',
  email: ''
};

function reducer(state, action) {
  switch (action.type) {
    case 'setName':
      return { ...state, name: action.payload };
    case 'setEmail':
      return { ...state, email: action.payload };
    default:
      return state;
  }
}

export default function Form() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <input
        type="text"
        value={state.name}
        onChange={(e) => dispatch({ type: 'setName', payload: e.target.value })}
        placeholder="Name"
      />
      <input
        type="email"
        value={state.email}
        onChange={(e) => dispatch({ type: 'setEmail', payload: e.target.value })}
        placeholder="Email"
      />
      <p>Name: {state.name}</p>
      <p>Email: {state.email}</p>
    </div>
  );
}




Nach dem Login kopieren

Der Reduzierer verarbeitet drei Aktionen:

  • SELECT_OPTION: Wenn der Benutzer eine Antwort auswählt
  • NÄCHSTE_FRAGE: Beim Übergang zur nächsten Frage
  • NEUSTART: Beim Neustart des Quiz

Styling-Logik

import React, { useReducer } from 'react';

// Quiz data with detailed explanations
const quizData = [
  {
    question: "What hook is used to handle complex state logic in React?",
    options: ["useState", "useReducer", "useEffect", "useContext"],
    correct: 1,
    explanation: "useReducer is specifically designed for complex state management scenarios."
  },
  {
    question: "Which function updates the state in useReducer?",
    options: ["setState", "dispatch", "update", "setReducer"],
    correct: 1,
    explanation: "dispatch is the function provided by useReducer to trigger state updates."
  },
  {
    question: "What pattern is useReducer based on?",
    options: ["Observer Pattern", "Redux Pattern", "Factory Pattern", "Module Pattern"],
    correct: 1,
    explanation: "useReducer is inspired by Redux's state management pattern."
  }
];

// Initial state with feedback state added
const initialState = {
  currentQuestion: 0,
  score: 0,
  showScore: false,
  selectedOption: null,
  showFeedback: false, // New state for showing answer feedback
};

// Enhanced reducer with feedback handling
const reducer = (state, action) => {
  switch (action.type) {
    case 'SELECT_OPTION':
      return {
        ...state,
        selectedOption: action.payload,
        showFeedback: true, // Show feedback when option is selected
      };
    case 'NEXT_QUESTION':
      const isCorrect = action.payload === quizData[state.currentQuestion].correct;
      const nextQuestion = state.currentQuestion + 1;
      return {
        ...state,
        score: isCorrect ? state.score + 1 : state.score,
        currentQuestion: nextQuestion,
        showScore: nextQuestion === quizData.length,
        selectedOption: null,
        showFeedback: false, // Reset feedback for next question
      };
    case 'RESTART':
      return initialState;
    default:
      return state;
  }
};

const Quiz = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
  const { currentQuestion, score, showScore, selectedOption, showFeedback } = state;

  const handleOptionClick = (optionIndex) => {
    dispatch({ type: 'SELECT_OPTION', payload: optionIndex });
  };

  const handleNext = () => {
    if (selectedOption !== null) {
      dispatch({ type: 'NEXT_QUESTION', payload: selectedOption });
    }
  };

  const handleRestart = () => {
    dispatch({ type: 'RESTART' });
  };

  if (showScore) {
    return (
      <div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-4">
        <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
          <h2 className="text-2xl font-bold text-center mb-4">Quiz Complete!</h2>
          <p className="text-xl text-center mb-6">
            Your score: {score} out of {quizData.length}
          </p>
          <button
            onClick={handleRestart}
            className="w-full bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600 transition-colors"
          >
            Restart Quiz
          </button>
        </div>
      </div>
    );
  }

  const currentQuizData = quizData[currentQuestion];
  const isCorrectAnswer = (optionIndex) => optionIndex === currentQuizData.correct;

  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-4">
      <div className="bg-white rounded-lg shadow-lg p-8 max-w-md w-full">
        <div className="mb-6">
          <p className="text-sm text-gray-500 mb-2">
            Question {currentQuestion + 1}/{quizData.length}
          </p>
          <h2 className="text-xl font-semibold mb-4">{currentQuizData.question}</h2>
        </div>

        <div className="space-y-3 mb-6">
          {currentQuizData.options.map((option, index) => {
            let buttonStyle = 'bg-gray-50 hover:bg-gray-100';

            if (showFeedback && selectedOption === index) {
              buttonStyle = isCorrectAnswer(index) 
                ? 'bg-green-100 border-2 border-green-500 text-green-700'
                : 'bg-red-100 border-2 border-red-500 text-red-700';
            }

            return (
              <button
                key={index}
                onClick={() => handleOptionClick(index)}
                disabled={showFeedback}
                className={`w-full p-3 text-left rounded-lg transition-colors ${buttonStyle}`}
              >
                {option}
              </button>
            );
          })}
        </div>

        {showFeedback && (
          <div className={`p-4 rounded-lg mb-4 ${
            isCorrectAnswer(selectedOption)
              ? 'bg-green-50 text-green-800'
              : 'bg-red-50 text-red-800'
          }`}>
            {isCorrectAnswer(selectedOption)
              ? "Correct! "
              : `Incorrect. The correct answer was: ${currentQuizData.options[currentQuizData.correct]}. `}
            {currentQuizData.explanation}
          </div>
        )}

        <button
          onClick={handleNext}
          disabled={!showFeedback}
          className={`w-full py-2 px-4 rounded transition-colors ${
            !showFeedback
              ? 'bg-gray-300 cursor-not-allowed'
              : 'bg-blue-500 text-white hover:bg-blue-600'
          }`}
        >
          Next Question
        </button>
      </div>
    </div>
  );
};

export default Quiz;


Nach dem Login kopieren

Dieser Code bestimmt den Button-Stil:

  • Standard: Grauer Hintergrund
  • Richtige Antwort: Grüner Hintergrund mit grünem Rand
  • Falsche Antwort: Roter Hintergrund mit rotem Rand

Feedback-Anzeige

// Initial state
const initialState = {
  currentQuestion: 0,
  score: 0,
  showScore: false,
  selectedOption: null,
  showFeedback: false, // New state for feedback
};
Nach dem Login kopieren

Dies zeigt Feedback, nachdem eine Antwort ausgewählt wurde:

*Zeigt an, ob die Antwort richtig oder falsch war
*Zeigt die richtige Antwort, wenn sie falsch ist
*Enthält eine Erklärung

Gehosteter Link der Quiz-App

quiztechnicalwriting.vercel.app

Vergleich zwischen useState und useReducer

Feature useState useReducer
Best for Simple state Complex state logic
State Management Direct, using setState Managed through a reducer function
Boilerplate Code Minimal Requires more setup
State Update Inline with setState Managed by dispatch and reducer

Abschluss

Sowohl useState als auch useReducer sind leistungsstarke Hooks für die Zustandsverwaltung in Funktionskomponenten. useState eignet sich am besten für einfache Zustände, während useReducer bei der Handhabung komplexerer Szenarien glänzt, bei denen Zustandsaktualisierungen eng miteinander verbunden sind. Die Wahl des richtigen hängt von der Komplexität des Zustands ab, den Sie verwalten müssen.

Das obige ist der detaillierte Inhalt vonuseReducer und wie es sich von useState unterscheidet. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage