For complex state operation logic and nested state objects, useReducer is recommended

use

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

The userReducer receives two parameters, a Reducer function and an initialization state.

UseReducer returns the latest state and dispath, state is the value in the returned state, and Dispatch is a method that can publish the time to update state.

Reducer accepts two parameters, state and Action.

Reducer is A pure function that converts state from A to B using the information provided by action. Reducer has the following characteristics

  • Syntax :(state, action) => newState
  • Immutable: Return a newState each time, never modify the state object directly
  • Action: A regular Action object usually consists of type and optional payload
  • Type: Indicates the operation type, which is the basis for the reducer conditions
  • Payload: Provides data information associated with an operation

Simple usage examples:

function UseReducerDemo () {
  // Define the initial state
  const initState = { count: 0 }
  // Reducer
  function reducer (state, action) {
    switch (action.type) {
      case 'add':
        return { count: state.count + 1 };
      case 'sub':
        return { count: state.count - 1 };
      default:
        throw new Error()}}// return the new state
  const [state, dispatch] = useReducer(reducer, initState)
  return (
    <div>
      <div>count: {state.count}</div>
      <button onClick={()= > dispatch({ type: 'add' })}>add</button>
      <button onClick={()= > dispatch({ type: 'sub' })}>sub</button>
    </div>
  );
}
Copy the code

A simple example comparing useState and useReducer:

useState:

import React, { useState } from 'react';
import submitInfo from './api';
function UseStateDemo () {
  const [name, setName] = useState(' ')
  const [sex, setSex] = useState(0)
  const [age, setAge] = useState(0)
  const [avatar, setAvatar] = useState(' ')
  const [interests, setInterests] = useState([])
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(' ')
  const submit = (event) = > {
    event.preventDefault();
    setError(' ');
    setLoading(true);
    const param = {
      name,
      sex,
      age,
      avatar,
      interests
    }
    submitInfo({ param })
      .then(() = > {
        setLoading(false);
      })
      .catch((error) = > {
        setError(error.message);
        setName(' ');
        setSex(0);
        setAge(0);
        setAvatar(' ');
        setInterests([])
        setLoading(false);
      });
  }
  const reset = () = > {
    setName(' ');
    setSex(0);
    setAge(0);
    setAvatar(' ');
    setInterests([])
    setLoading(false);
  }
  return (
    <div>{/* jsx demo... * /}<button onClick={()= > submit()}></button>
      <button onClick={()= > reset()}></button>
    </div>
  );
}
export default UseStateDemo;
Copy the code

useReducer:

import React, { useReducer } from 'react';
import submitInfo from './api'
function UseReducerDemo () {
  const initialState = {
    name: ' '.sex: 0.age: 0.avatar: ' '.interests: [].loading: false.error: ' '
  }
  const reducer = (state, action) = > {
    switch (action.type) {
      case 'submit':
        return { ...state, loading: false };
      case 'reset':
        return {
          ...state,
          name: ' '.sex: 0.age: 0.avatar: ' '.interests: []};default:
        return state
    }
  }
  const [state, dispatch] = useReducer(reducer, initialState)
  const submit = (event) = > {
    event.preventDefault();
    const {
      name,
      sex,
      age,
      avatar,
      interests
    } = state
    const param = {
      name,
      sex,
      age,
      avatar,
      interests
    }
    submitInfo({ param })
      .then(() = > {
        dispatch('submit')
      })
      .catch((error) = > {
        dispatch('reset')}); }return (
    <div>{/* jsx demo... * /}<button onClick={()= > submit()}></button>
      <button onClick={()= > dispatch('reset')}></button>
    </div>
  );
}
export default UseReducerDemo;
Copy the code

In contrast, useReducer makes the code more readable and the state update logic clearer. Suitable use scenarios:

  • If state is an array or an object
  • If the state changes are complex, often many states need to be changed in one operation
  • If you want to build automated test cases to ensure the stability of the application
  • If you need to modify some state in a deep subcomponent (more on this in the next article)
  • If you have a large application, you want the UI and business to be maintained separately

Reference (zhuanlan.zhihu.com/p/69622832)