React learning the duodécimo día React Hooks analiza las funciones después de react16.8

Tabla de contenido:

1 Conoce y experimenta Hooks

2 Estado/Efecto

3 Contexto/Reductor

4 Devolución de llamada/Memo

5 Efecto de referencia/diseño

Uso de 6 ganchos personalizados

Después de eso, puede usar ganchos para desarrollar más, pero aún necesita saber cómo usar los componentes de clase.

1. Conoce y experimenta Hooks

Las funciones son el defecto de los componentes:

1. Cambiar las variables en el componente de la función no activará la renderización para volver a renderizar

2. Las condiciones que pueden desencadenar una nueva representación, porque no hay lugar para guardar el nuevo valor de la variable, el valor final de la variable representada sigue siendo el valor predeterminado

3. No hay ciclo de vida

 Desventajas de los componentes de clase:

(1) Cuando la lógica es compleja, el código está inflado

(2) La clase en sí es compleja, ¿a qué apunta esto?

(3) Necesita usar funciones de orden superior para darse cuenta del uso de algunas cosas

 El uso de ganchos puede simplificar la cantidad de código, parecer conciso y ya no tener estos problemas de señalización.

Los ganchos deben usarse en el nivel superior de la función; de lo contrario, se informará un error

correcto:

Error:

Los ganchos no se pueden usar en componentes de clase, ni se pueden usar ganchos en otras funciones ordinarias. Pero los ganchos se pueden usar en ganchos personalizados.

Las funciones ordinarias que usan ganchos reportarán un error:

Está permitido usar otros ganchos en ganchos personalizados:

 

 

 

 

2. Estado/Efecto

1. const [El primer parámetro es el valor devuelto, el segundo parámetro es la función original para restablecer el valor almacenado] = useState (valor inicial) debe tener un valor entre paréntesis, de lo contrario, el valor inicial no está definido

El primer parámetro es similar a this.state;, el segundo parámetro es similar a setState

(1) Cuando se llama a la función, se destruirá y la variable dentro desaparecerá. useState es equivalente a guardar esta variable en otra función de reaccionar, y luego sacarla y reutilizarla, y llamar a la función para modificar la el valor de la variable es equivalente a Al llamar a la función que contiene la variable

2. Los efectos secundarios significan algunas funciones adicionales que se pueden usar una vez que se completa la representación de la página, como solicitudes de red, ciclo de vida, operaciones dom, etc.

(1) useEffect (los efectos secundarios deben colocarse en un lugar separado):

Los siguientes efectos secundarios no se colocan en un lugar separado:

Los siguientes efectos secundarios se colocan en lugares separados:

(2) Borrar algunos eventos de escucha en efectos secundarios (mecanismo de limpieza)

Tenga en cuenta que el código en useEffect se ejecutará una vez cada vez que se actualicen los datos, y (4) hablará sobre cómo hacer que el código de useEffect solo se ejecute una vez.

 La forma de cancelar el monitoreo es escribir una función de retorno

(3) Se pueden usar múltiples efectos de uso en un componente para colocar diferentes códigos respectivamente

(4) Optimización del rendimiento de UseEffect, control de la ejecución de devolución de llamada, de modo que algunas cosas solo se ejecuten una vez o alguien las cambie.

Si necesita controlar la ejecución de un determinado código debido a los cambios, escriba una matriz en el segundo parámetro de useEffect y escriba a quién afecta en la matriz:

Solo necesita escribir una matriz vacía [] en el segundo parámetro de useEffect para ejecutarlo solo una vez cuando se carga el componente, y no importa quién cambie en el futuro, la función envuelta por useEffect no se ejecutará:

 

 

 

 

三、Contexto/Reductor

Los ganchos subsiguientes tienden a usarse en escenarios especiales, y useState y useEffect anteriores son los conceptos básicos que deben devolverse.

1. El uso de useContext:

(1) Cree una carpeta de contexto y un archivo index.js:

(2) El archivo index.js correspondiente a App.jsx proporciona datos:

(3) Utilice los parámetros proporcionados en el App.jsx envuelto:

2, useReducer (entender)

Reemplazo equivalente para useState

El escenario de uso de useReducer es como se muestra en la figura a continuación. Se pueden administrar varios parámetros a la vez, pero el código para modificar los parámetros debe colocarse en el reductor, que no es fácil de operar:

 Cómo usar useReducer:

import React, { memo, useReducer } from 'react'
// import { 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
  }
}

// useReducer+Context => redux

const App = memo(() => {
  // const [count, setCount] = useState(0)
  const [state, dispatch] = useReducer(reducer, { counter: 0, friends: [], user: {} })

  // const [counter, setCounter] = useState()
  // const [friends, setFriends] = useState()
  // const [user, setUser] = useState()

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

export default App

 

4. Devolución de llamada/Memo

Nota: si realmente no lo entiende, solo necesita saber que cuando el componente principal quiera pasar una función al componente secundario en el futuro, debe ser envuelto por useCallback.

1. useCallback se utiliza para la optimización del rendimiento

(1) Análisis de la razón: cuando se llama y se vuelve a representar una función definida en un componente funcional, la función se redefinirá y luego se destruirá la función original.

 La función anterior se destruye.

(2) El uso de useCallback puede optimizar el código que usa cada vez o la función envuelta por la devolución de llamada original, pero la función envuelta aún se redefinirá cada vez que se vuelva a representar el componente funcional, por lo que no tiene ningún efecto.

(3) Trampa de devolución de llamada:

(4) useCallback generalmente se usa para optimizar cuando el componente principal pasa funciones al componente secundario, a fin de evitar que el componente principal permita que el componente secundario vuelva a procesar y ejecute la función del componente secundario para reducir el rendimiento. La razón es que si hay muchas funciones en el componente secundario y una de las funciones se pasa desde el componente principal, cuando el componente principal se vuelve a representar, la función se volverá a crear y los accesorios del componente secundario se volverán a generar. obtenido del componente principal. La función también se vuelve a adquirir, el subcomponente se vuelve a renderizar y muchas funciones en el subcomponente también se vuelven a crear. Cae el rendimiento.

import React, { memo, useState, useCallback, useRef } from 'react'

// useCallback性能优化的点:
// 1.当需要将一个函数传递给子组件时, 最好使用useCallback进行优化, 将优化之后的函数, 传递给子组件

// props中的属性发生改变时, 组件本身就会被重新渲染
const HYHome = memo(function(props) {
  const { increment } = props
  console.log("HYHome被渲染")
  return (
    <div>
      <button onClick={increment}>increment+1</button>

      {/* 100个子组件 */}
    </div>
  )
})

const App = memo(function() {
  const [count, setCount] = useState(0)
  const [message, setMessage] = useState("hello")

  // 闭包陷阱: useCallback
  // const increment = useCallback(function foo() {
  //   console.log("increment")
  //   setCount(count+1)
  // }, [count])

  // 进一步的优化: 当count发生改变时, 也使用同一个函数(了解)
  // 做法一: 将count依赖移除掉, 缺点: 闭包陷阱
  // 做法二: useRef, 在组件多次渲染时, 返回的是同一个值
  const countRef = useRef()
  countRef.current = count
  const increment = useCallback(function foo() {
    console.log("increment")
    setCount(countRef.current + 1)
  }, [])

  // 普通的函数
  // const increment = () => {
  //   setCount(count+1)
  // }

  return (
    <div>
      <h2>计数: {count}</h2>
      <button onClick={increment}>+1</button>

      <HYHome increment={increment}/>

      <h2>message:{message}</h2>
      <button onClick={e => setMessage(Math.random())}>修改message</button>
    </div>
  )
})


// function foo(name) {
//   function bar() {
//     console.log(name)
//   }
//   return bar
// }

// const bar1 = foo("why")
// bar1() // why
// bar1() // why

// const bar2 = foo("kobe")
// bar2() // kobe

// bar1() // why

export default App

Nota: La diferencia entre useCallback y usememo es que el primero devuelve una función, mientras que el segundo devuelve un valor.

En pocas palabras, la función de useMemo es evitar que los componentes funcionales se vuelvan a representar debido a un cambio de parámetro, mientras que otras funciones ejecutan varias funciones repetidamente y evitan que los parámetros de tipo de objeto pasados ​​a los subcomponentes vuelvan a crear objetos debido a la nueva representación del componente. y los subcomponentes encuentran cambios en los objetos, los componentes secundarios se vuelven a renderizar sin sentido.

2. usememo se usa para optimizar componentes de funciones individuales.Algunas funciones cambian las variables y hacen que todo el componente se vuelva a renderizar, y todas las demás funciones del componente se vuelven a ejecutar, lo que desperdicia rendimiento.

import React, { memo, useCallback } from 'react'
import { useMemo, useState } from 'react'


const HelloWorld = memo(function(props) {
  console.log("HelloWorld被渲染~")
  return <h2>Hello World</h2>
})


function calcNumTotal(num) {
  // console.log("calcNumTotal的计算过程被调用~")
  let total = 0
  for (let i = 1; i <= num; i++) {
    total += i
  }
  return total
}

const App = memo(() => {
  const [count, setCount] = useState(0)

  // const result = calcNumTotal(50)

  // 1.不依赖任何的值, 进行计算
  const result = useMemo(() => {
    return calcNumTotal(50)
  }, [])

  // 2.依赖count
  // const result = useMemo(() => {
  //   return calcNumTotal(count*2)
  // }, [count])

  // 3.useMemo和useCallback的对比
  function fn() {}
  // const increment = useCallback(fn, [])
  // const increment2 = useMemo(() => fn, [])


  // 4.使用useMemo对子组件渲染进行优化
  // const info = { name: "why", age: 18 }
  const info = useMemo(() => ({name: "why", age: 18}), [])

  return (
    <div>
      <h2>计算结果: {result}</h2>
      <h2>计数器: {count}</h2>
      <button onClick={e => setCount(count+1)}>+1</button>

      <HelloWorld result={result} info={info} />
    </div>
  )
})

export default App

 

Ejemplo, Ref/LayoutEffect

1. useRef tiene dos usos:

(1) DOM vinculante

(2) Valor de enlace para resolver la trampa de cierre

import React, { memo, useRef } from 'react'

const App = memo(() => {
  const titleRef = useRef()
  const inputRef = useRef()
  
  function showTitleDom() {
    console.log(titleRef.current)
    inputRef.current.focus()
  }

  return (
    <div>
      <h2 ref={titleRef}>Hello World</h2>
      <input type="text" ref={inputRef} />
      <button onClick={showTitleDom}>查看title的dom</button>
    </div>
  )
})

export default App
import React, { memo, useRef } from 'react'
import { useCallback } from 'react'
import { useState } from 'react'

let obj = null

const App = memo(() => {
  const [count, setCount] = useState(0)
  const nameRef = useRef()
  console.log(obj === nameRef)
  obj = nameRef

  // 通过useRef解决闭包陷阱
  const countRef = useRef()
  countRef.current = count

  const increment = useCallback(() => {
    setCount(countRef.current + 1)
  }, [])

  return (
    <div>
      <h2>Hello World: {count}</h2>
      <button onClick={e => setCount(count+1)}>+1</button>
      <button onClick={increment}>+1</button>
    </div>
  )
})

export default App

2, use ImperativeHandle

import React, { memo, useRef, forwardRef, useImperativeHandle } from 'react'

const HelloWorld = memo(forwardRef((props, ref) => {

  const inputRef = useRef()

  // 子组件对父组件传入的ref进行处理
  useImperativeHandle(ref, () => {
    return {
      focus() {
        console.log("focus")
        inputRef.current.focus()
      },
      setValue(value) {
        inputRef.current.value = value
      }
    }
  })

  return <input type="text" ref={inputRef}/>
}))


const App = memo(() => {
  const titleRef = useRef()
  const inputRef = useRef()

  function handleDOM() {
    // console.log(inputRef.current)
    inputRef.current.focus()
    // inputRef.current.value = ""
    inputRef.current.setValue("哈哈哈")
  }

  return (
    <div>
      <h2 ref={titleRef}>哈哈哈</h2>
      <HelloWorld ref={inputRef}/>
      <button onClick={handleDOM}>DOM操作</button>
    </div>
  )
})

export default App

3, useLayoutEffect

(1) El tiempo de ejecución de useLayoutEffect y useEffect es diferente 

(2) useLayoutEffect puede evitar el parpadeo de la pantalla en algunos casos

Tiempo de ejecución:

import React, { memo, useEffect, useLayoutEffect, useState } from 'react'

const App = memo(() => {
  const [count, setCount] = useState(0)
  
  useLayoutEffect(() => {
    console.log("useLayoutEffect")
  })

  useEffect(() => {
    console.log("useEffect")
  })

  console.log("App render")

  return (
    <div>
      <h2>count: {count}</h2>
      <button onClick={e => setCount(count + 1)}>+1</button>
    </div>
  )
})

export default App

Alternar número useEffect:

import React, { memo, useEffect, useLayoutEffect, useState } from 'react'

const App = memo(() => {
  const [count, setCount] = useState(100)

  useEffect(() => {
    console.log("useEffect")
    if (count === 0) {
      setCount(Math.random() + 99)
    }
  })

  console.log("App render")

  return (
    <div>
      <h2>count: {count}</h2>
      <button onClick={e => setCount(0)}>设置为0</button>
    </div>
  )
})

export default App

Alternar números -useLayoutEffect:

import React, { memo, useEffect, useLayoutEffect, useState } from 'react'

const App = memo(() => {
  const [count, setCount] = useState(100)

  useLayoutEffect(() => {
    console.log("useLayoutEffect")
    if (count === 0) {
      setCount(Math.random() + 99)
    }
  })

  console.log("App render")

  return (
    <div>
      <h2>count: {count}</h2>
      <button onClick={e => setCount(0)}>设置为0</button>
    </div>
  )
})

export default App

 

6. Uso de Hooks personalizados

 

Supongo que te gusta

Origin blog.csdn.net/weixin_56663198/article/details/129269951
Recomendado
Clasificación