[Conocimiento de front-end] Consolidación de la base de React (cuarenta y cuatro) - otros Hooks (useContext, useReducer, useCallback)

Consolidación de la base React (cuarenta y cuatro): otros ganchos (useContext, useReducer, useCallback)

1. El uso de useContext

Al desarrollar componentes de clase, usamos 类名.contextType = MyContextel método para obtener contexto en la clase, múltiples contextos o MyContext.Consumercompartir contexto en componentes funcionales:

import React, {
    
     memo } from 'react'
import {
    
     UserContext, ThemeContext } from './context'

export default memo(function App() {
    
    

// 使用Context

  return (
    <div>
      <UserContext.Consumer>
        {
    
    
          value => {
    
    
            return (
              <h2>
                <ThemeContext.Consumer>
                  {
    
    
                    value => {
    
    
                      <span></span>
                    }
                  }
                </ThemeContext.Consumer>
              </h2>
            )
          }
        }
      </UserContext.Consumer>
    </div>
  )
})

Se puede ver que cuando necesitamos usar múltiples Contextos, hay muchos códigos anidados engorrosos; y Context Hook nos permite obtener directamente el valor de un Contexto a través de Hook, de la siguiente manera:

import React, {
    
     memo, useContext } from "react";
import {
    
     ThemeContext, UserContext } from "./context";

export default memo(function App() {
    
    
  // 使用Context
  const user = useContext(UserContext);
  const theme = useContext(ThemeContext);

  return (
    <div>
      <h2>
        User: {
    
    user.name} - {
    
    user.age}
      </h2>
      <h2>
        Theme: {
    
    theme.color} - {
    
    theme.size}
      </h2>
    </div>
  );
});

Se puede ver que Context Hook solo usa dos líneas de código para reemplazar el complicado código anidado anterior, que es muy eficiente y conciso.

En segundo lugar, el uso de useReducer

useReducer es una alternativa a useState.Cuando la lógica de procesamiento de estado es compleja, puede usar useReducer para dividirla, o puede usar useReducer cuando necesite confiar en el estado anterior al modificar el estado.

Hay muy pocos escenarios utilizados por useReducer, y generalmente se usa en escenarios que requieren administración unificada y modificación de múltiples datos. Por ejemplo, cuando necesitamos procesar múltiples datos de manera unificada, si usamos useState, debemos definirlo varias veces, y el reductor puede definirlo y modificarlo de manera uniforme:

import React, {
    
     memo, useReducer, useState } from "react";

function reducer(state, action) {
    
    
  switch (action.type) {
    
    
    case "increment":
      return {
    
     ...state, counter: state.counter + 1 };
    case "decrement":
      return {
    
     ...state, counter: state.counter - 1 };
    case "add_number":
      return {
    
     ...state, counter: state.counter + action.num };
    case "sub_number":
      return {
    
     ...state, counter: state.counter - action.num };
    default:
      return state;
  }
}

export default memo(function App() {
    
    
  // const [count, setCount] = useState(0);
  // const [user, setUser] = useState(0);
  // const [list, setList] = useState(0);

  const [state, dispatch] = useReducer(reducer, {
    
    
    counter: 0,
    user: {
    
    },
    list: [],
  });

  return (
    <div>
      {
    
    /* <h2>当前计数:{count}</h2>
      <button onClick={(e) => setCount(count + 1)}>+1</button>
      <button onClick={(e) => setCount(count - 1)}>-1</button>
      <button onClick={(e) => setCount(count + 5)}>+5</button>
      <button onClick={(e) => setCount(count - 5)}>-5</button>
      <button onClick={(e) => setCount(count + 100)}>+100</button> */}

      <h2>当前计数:{
    
    state.counter}</h2>
      <button onClick={
    
    (e) => dispatch({
    
     type: "increment" })}>+1</button>
      <button onClick={
    
    (e) => dispatch({
    
     type: "decrement" })}>-1</button>
      <button onClick={
    
    (e) => dispatch({
    
     type: "add_number", num: 5 })}>
        +5
      </button>
      <button onClick={
    
    (e) => dispatch({
    
     type: "sub_number", num: 5 })}>
        -5
      </button>
      <button onClick={
    
    (e) => dispatch({
    
     type: "add_number", num: 100 })}>
        +100
      </button>
    </div>
  );
});

3. Uso de useCallback

El propósito real de useCallback es para la optimización del rendimiento. useCallback devolverá un valor memorizado (memorizado) de una función. Cuando la dependencia permanece sin cambios, el valor devuelto es el mismo cuando se define varias veces.

Optimización del rendimiento de useCallback:

  1. Cuando es necesario pasar una función a un subcomponente, useCallback se puede usar para la optimización y la función optimizada se puede pasar al subcomponente

    import React, {
          
           memo, useCallback, useState } from "react";
    
    const HYIncrement = memo(function (props) {
          
          
      const {
          
           increment } = props;
    
      console.log("HYIncrement被渲染");
    
      return (
        <div>
          <button onClick={
          
          increment}>increment + 1</button>
        </div>
      );
    });
    
    export default memo(function App() {
          
          
      const [count, setCount] = useState(0);
      const [message, setMessage] = useState("hello");
    
      // 使用useCallback
      const increment = useCallback(
        function () {
          
          
          setCount(count + 1);
        },
        [count]
      );
    
      // 普通函数
      // const increment = () => {
          
          
      //   setCount(count + 1);
      // };
    
      return (
        <div>
          <h2>计数:{
          
          count}</h2>
          <button onClick={
          
          increment}>+1</button>
    
          <HYIncrement increment={
          
          increment} />
    
          <h2>message:{
          
          message}</h2>
          <button onClick={
          
          (e) => setMessage("world")}>修改 message</button>
        </div>
      );
    });
    
    
  2. optimización avanzada

    Cuando el conteo cambia, también use la misma función

      // 做法一:将count依赖移除掉,缺点:存在闭包陷阱,不依赖count后setCount每次拿到的count并非最新的count
      // const increment = useCallback(function foo() {
          
          
      //   console.log("increment");
      //   setCount(count + 1);
      // }, []);
    
      // 做法二:利用useRef,在组件多次渲染时,返回同一个值
      const countRef = useRef();
      countRef.current = count;
      const increment = useCallback(
        function foo() {
          
          
          console.log("increment");
          setCount(countRef.current + 1);
        },
        []
      );
    

Supongo que te gusta

Origin blog.csdn.net/weixin_42919342/article/details/132051382
Recomendado
Clasificación