useReducer

import { useReducer, useState } from "react";

const initialState = { count: 0 };

function reducer(state, action) {
  console.log("Current state:", state);
  console.log("Action received:", action);

  switch (action.type) {
    case "INCREMENT":
      return { ...state, count: state.count + (action.payload ?? 1) };
    case "DECREMENT":
      return { ...state, count: state.count - (action.payload ?? 1) };
    default:
      return state;
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, initialState);
  const [value, setValue] = useState("");

  const increase = () => {
    dispatch({ type: "INCREMENT" });
  };

  const decrease = () => {
    dispatch({ type: "DECREMENT" });
  };

  const customIncrease = () => {
    dispatch({ type: "INCREMENT", payload: Number(value) });
  };

  const customDecrease = () => {
    dispatch({ type: "DECREMENT", payload: Number(value) });
  };

  return (
    <>
      <h1>Count: {state.count}</h1>

      <button onClick={increase}>+</button>
      <button onClick={decrease}>-</button>

      <hr />

      <input
        type="number"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        placeholder="Enter number"
      />

      <button onClick={customIncrease}>Custom +</button>
      <button onClick={customDecrease}>Custom -</button>
    </>
  );
}

export default App;

useState

import { useState } from "react";

function App() {
  const [count, setCount] = useState(0);
  const [value, setValue] = useState("");

  const increase = () => {
    setCount((prev) => prev + 1);
  };

  const decrease = () => {
    setCount((prev) => prev - 1);
  };

  const customIncrease = () => {
    setCount((prev) => prev + Number(value));
  };

  const customDecrease = () => {
    setCount((prev) => prev - Number(value));
  };

  return (
    <>
      <h1>Count: {count}</h1>

      <button onClick={increase}>+</button>
      <button onClick={decrease}>-</button>

      <hr />

      <input
        type="number"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        placeholder="Enter number"
      />

      <button onClick={customIncrease}>Custom +</button>
      <button onClick={customDecrease}>Custom -</button>
    </>
  );
}

export default App;

From the example above, useState is better. Only 1 value


useReducer

import { useReducer } from "react";

const initialState = {
  email: "",
  password: "",
  loading: false,
  error: "",
  loggedIn: false,
};

function reducer(state, action) {
  switch (action.type) {
    case "SET_EMAIL":
      return {
        ...state,
        email: action.payload,
      };

    case "SET_PASSWORD":
      return {
        ...state,
        password: action.payload,
      };

    case "LOGIN_START":
      return {
        ...state,
        loading: true,
        loggedIn: false,
        error: "",
      };

    case "LOGIN_SUCCESS":
      return {
        ...state,
        loading: false,
        loggedIn: true,
      };

    case "LOGIN_ERROR":
      return {
        ...state,
        loading: false,
        loggedIn: true,
        error: action.payload,
      };

    default:
      return state;
  }
}

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

  const login = () => {
    dispatch({ type: "LOGIN_START" });

    setTimeout(() => {
      if (state.email === "[email protected]" && state.password === "123") {
        dispatch({ type: "LOGIN_SUCCESS" });
      } else {
        dispatch({ type: "LOGIN_ERROR", payload: "Invalid credentials" });
      }
    }, 1000);
  };

  return (
    <>
      <input
        placeholder="Email"
        value={state.email}
        onChange={(e) =>
          dispatch({
            type: "SET_EMAIL",
            payload: e.target.value,
          })
        }
      />

      <input
        type="password"
        placeholder="Password"
        value={state.password}
        onChange={(e) =>
          dispatch({
            type: "SET_PASSWORD",
            payload: e.target.value,
          })
        }
      />

      <button onClick={login}>
        Login
      </button>

      {state.loading && <p>Loading...</p>}
      {state.error && <p>{state.error}</p>}
      {state.loggedIn && <p>Login success</p>}
    </>
  );
}

  export default App;

useState

import { useState } from "react";

function App() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [loggedIn, setLoggedIn] = useState(false);

  const login = () => {
    setLoading(true);
    setError("");

    setTimeout(() => {
      if (email === "[email protected]" && password === "123") {
        setLoggedIn(true);
      } else {
        setError("Invalid credentials");
      }

      setLoading(false);
    }, 1000);
  };

  return (
    <>
      <input
        placeholder="Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />

      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />

      <button onClick={login}>
        Login
      </button>

      {loading && <p>Loading...</p>}

      {error && <p>{error}</p>}

      {loggedIn && <p>Login success</p>}
    </>
  );
}

export default App;