Rumah  >  Artikel  >  hujung hadapan web  >  useReducer dan bagaimana ia berbeza daripada useState

useReducer dan bagaimana ia berbeza daripada useState

Susan Sarandon
Susan Sarandonasal
2024-10-30 20:04:30617semak imbas

useReducer and how it is different from useState

Jadual Kandungan

  1. Pengenalan
  2. Bila Gunakan useState
  3. Bila Gunakan useReducer
  4. Contoh 1: Apl Kaunter dengan useState
  5. Contoh 2: Apl Kaunter dengan useReducer
  6. Contoh 3: Pengendalian Input Borang dengan useReducer
  7. Contoh 4: Membina apl kuiz dengan useReducer
  8. Perbandingan Antara useState dan useReducer
  9. Kesimpulan

pengenalan

React menawarkan dua cangkuk utama untuk menguruskan keadaan: useState dan useReducer. Walaupun kedua-duanya direka bentuk untuk mengendalikan keadaan dalam komponen berfungsi, ia digunakan dalam senario yang berbeza. Artikel ini meneroka perbezaan antara kedua-duanya dan menyerlahkan masa anda harus menggunakan setiap satu, dengan contoh untuk pemahaman yang lebih baik

Bila hendak menggunakan useState

useState ialah cangkuk yang mudah dan berkesan untuk mengendalikan keadaan setempat apabila:

  • Anda mempunyai keadaan mudah untuk diurus (seperti boolean, nombor atau rentetan).
  • Anda mahu kemas kini langsung dinyatakan dengan persediaan minimum.
  • Keadaan tidak mempunyai peralihan atau kebergantungan yang kompleks pada berbilang pembolehubah.

Sintaks Asas

const [state, setState] = useState(initialState);
  • keadaan: Keadaan semasa.
  • setState: Fungsi untuk mengemas kini keadaan.
  • Keadaan permulaan:Keadaan awal

Bila Menggunakan useReducer

useReducer berguna apabila:

  • Anda mempunyai logik keadaan yang kompleks.
  • Berbilang kemas kini keadaan bergantung antara satu sama lain.

Sintaks Asas

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

  • keadaan: Keadaan semasa.
  • penghantaran: Fungsi untuk menghantar tindakan kepada pengurang untuk mencetuskan kemas kini keadaan.
  • pengurang: Pengurangan ialah fungsi tulen yang mengambil dua hujah: keadaan semasa dan tindakan. Ia mengembalikan keadaan baharu berdasarkan tindakan.

Sintaks Asas

const reducer = (state, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { count: state.count + 1 };
        case 'DECREMENT':
            return { count: state.count - 1 };
        default:
            return state;
    }
}
  • Tindakan: Tindakan ialah objek yang menerangkan perubahan yang sepatutnya berlaku
    Ia biasanya mempunyai sifat jenis dan secara pilihan muatan.
    jenis memberitahu pengurang jenis perubahan keadaan yang perlu dibuat.
    muatan membawa sebarang data tambahan yang diperlukan untuk perubahan.

  • InitialState:Keadaan awal , sama seperti initialstate dalam useState.

Contoh 1 apl kaunter dengan useState

const [state, setState] = useState(initialState);

Penjelasan

  • Kami menggunakan useState untuk menjejak nilai kiraan.
  • Kami mempunyai dua butang: satu untuk menambah dan satu untuk mengurangkan keadaan kiraan.
  • Keadaan dikemas kini terus menggunakan fungsi setCount.

Contoh 2: Apl Kaunter dengan useReducer

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

Penjelasan

  • Fungsi pengurang mengawal cara keadaan harus berubah berdasarkan tindakan yang dihantar.
  • Daripada menetapkan keadaan secara langsung, kami menghantar tindakan (kenaikan, pengurangan) untuk mencetuskan perubahan.

Contoh 3: Pengendalian Input Borang dengan useReducer

Mari kembangkan konsep untuk mengendalikan borang dengan berbilang medan input. Senario ini sesuai untuk useReducer kerana ia mengemas kini berbilang sifat keadaan berdasarkan tindakan.

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

Penjelasan

  • Pengurang menguruskan keadaan borang dengan mengemas kini sifat yang berbeza (nama, e-mel) berdasarkan jenis tindakan.
  • Penghantaran menghantar tindakan kepada pengurang untuk mengemas kini keadaan. Muatan membawa data (cth., nilai input).

Contoh 4: Membina apl kuiz dengan useReducer

Nota: penggayaan telah dilakukan dengan tailwindcss

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>
  );
}


Penjelasan

*keadaan awal dengan 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>
  );
}

  • Fungsi Pengurang
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>
  );
}




Pengurang mengendalikan tiga tindakan:

  • SELECT_OPTION: Apabila pengguna memilih jawapan
  • SETERUSNYA_SOALAN: Apabila beralih ke soalan seterusnya
  • MULAKAN SEMULA: Apabila memulakan semula kuiz

Logik Penggayaan

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;


Kod ini menentukan gaya butang:

  • Lalai: Latar belakang kelabu
  • Jawapan betul: Latar belakang hijau dengan sempadan hijau
  • Jawapan salah: Latar belakang merah dengan jidar merah

Paparan Maklum Balas

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

Ini menunjukkan maklum balas selepas jawapan dipilih:

*Memaparkan sama ada jawapan itu betul atau salah
*Menunjukkan jawapan yang betul jika salah
*Termasuk penjelasan

Pautan dihoskan apl kuiz

quiztechnicalwriting.vercel.app

Perbandingan Antara useState dan 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

Kesimpulan

Kedua-dua useState dan useReducer ialah cangkuk berkuasa untuk menguruskan keadaan dalam komponen berfungsi. useState paling sesuai untuk keadaan mudah, manakala useReducer bersinar apabila mengendalikan senario yang lebih kompleks di mana kemas kini keadaan berkait rapat. Memilih yang betul bergantung pada kerumitan keadaan yang perlu anda uruskan.

Atas ialah kandungan terperinci useReducer dan bagaimana ia berbeza daripada useState. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn