El orden de ejecución del código dentro y fuera de retorno cuando useEffect tiene dependencias y no tiene dependencias

Se ha encontrado un problema en un proyecto reciente. El temporizador se llama una vez cada segundo para solicitar datos, y el temporizador se borra cuando el número alcanza el número total. Porque a veces la interfaz no puede llamar, por lo que el temporizador no se puede detener si no se alcanza el número total, y la página actual no se puede detener incluso si está cerrada a otras páginas. . Entonces, debe haber una página de cierre para borrar la operación del temporizador, así que pensé en el retorno del primer parámetro de función de useEffect.

1. El uso básico de useEffect

useEffect recibe dos parámetros, el primer parámetro es la función Effect; el segundo parámetro es un arreglo para evitar llamadas repetidas innecesarias de efectos; el segundo parámetro de useEffect se usa para definir variables dependientes, si se pasa un arreglo vacío, es decir, no hay elemento de cambio dependiente, solo se llamará una vez cuando se inicialice la página, si se agrega una dependencia, el cambio de una de las variables en el arreglo dependiente desencadenará la ejecución; cuando el segundo parámetro no existe, la función del primer parámetro de useEffect se ejecutará cada vez la página se actualiza;
por
ejemplo
:

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

function Demo () {
  const [count,setCount]=useState(0)
  useEffect(() => { 
    console.log('无依赖---------------------------',count)
  })
  useEffect(() => { 
    console.log('依赖为[]------------------------',count)
  },[])
  useEffect(() => { 
    console.log('依赖为[count]------------------------',count)
  },[count])
  return (
    <div>
      <p>count的值为: {count} </p>
      <button onClick={()=>setCount(count+1)}>add</button>
    </div>
  )
}

export default Demo

Inicializar el resultado de la ejecución:

无依赖--------------------------- 0
About.tsx:9 依赖为[]------------------------ 0
About.tsx:12 依赖为[count]------------------------ 0

El resultado después de hacer clic en agregar:

无依赖--------------------------- 1
About.tsx:12 依赖为[count]------------------------ 1

Dos, devuelve una función en useEffect

Con respecto al valor de retorno devuelto del primer parámetro de función de useEffect():

Los efectos secundarios ocurren cuando se carga el componente, por lo que cuando se descarga el componente, es posible que sea necesario limpiar estos efectos secundarios.
useEffect() permite devolver una función que se ejecuta cuando el componente se desmonta para limpiar los efectos secundarios. Si no necesita limpiar los efectos secundarios, useEffect() no tiene que devolver nada.

Para una mejor comprensión, veamos primero los resultados y luego resumamos, primero veamos el suplemento de ejemplo:

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

function Demo () {
  const [count,setCount]=useState(0)
  useEffect(() => { 
    console.log('无依赖---------------------------', count)
    return () => {
      console.log('执行  无依赖  时的return的函数')
    }
  })
  useEffect(() => { 
    console.log('依赖为[]------------------------', count)
    return () => {
      console.log('执行 依赖为[]  时的return的函数')
    }
  },[])
  useEffect(() => { 
    console.log('依赖为[count]------------------------', count)
    return () => {
      console.log('执行 依赖为[count]  时的return的函数')
    }
  },[count])
  return (
    <div>
      <p>count的值为: {count} </p>
      <button onClick={()=>setCount(count+1)}>add</button>
    </div>
  )
}

export default Demo

 1. La consola imprime el resultado durante la inicialización:

无依赖--------------------------- 0
依赖为[]------------------------ 0
依赖为[count]------------------------ 0
执行  无依赖  时的return的函数
执行 依赖为[]  时的return的函数
执行 依赖为[count]  时的return的函数
无依赖--------------------------- 0
依赖为[]------------------------ 0
依赖为[count]------------------------ 0

Se puede ver que cada función interna de useEffect se ejecuta dos veces durante la inicialización, porque estoy usando React 18, React 18 obligará a que el componente se actualice una vez en modo concurrente, y cada función de retorno también se ejecuta una vez cuando se fuerza la actualización. Es equivalente a realizar las siguientes operaciones: montar componente----quitar componente-volver a montar componente. Si es React 17, solo se montará una vez y el resultado impreso será:

无依赖--------------------------- 0
依赖为[]------------------------ 0
依赖为[count]------------------------ 0

2. El resultado de impresión de la consola después de hacer clic en el botón Agregar: 

执行  无依赖  时的return的函数
执行 依赖为[count]  时的return的函数
无依赖--------------------------- 1
依赖为[count]------------------------ 1

En este momento, la variable actualizada es count, por lo que se ejecuta el useEffect que escuchó el conteo, y también se ejecuta el useEffect sin el segundo parámetro. Cada vez, la función de retorno se ejecuta primero, y luego se ejecuta la parte fuera del retorno.

3. Al cambiar a otras páginas (es decir, al eliminar componentes), la consola imprime los resultados: 

执行  无依赖  时的return的函数
执行 依赖为[]  时的return的函数
执行 依赖为[count]  时的return的函数

En este momento, la parte de devolución se ejecuta en secuencia de acuerdo con el orden de usoEfecto

Notas sobre useEffect()

Hay una advertencia al usar useEffect(). Si hay múltiples efectos secundarios, se debe llamar a múltiples useEffect() en lugar de fusionarlos y escribirlos juntos.

Camino equivocado:

function App() {
  const [varA, setVarA] = useState(0);
  const [varB, setVarB] = useState(0);
  useEffect(() => {
    const timeoutA = setTimeout(() => setVarA(varA + 1), 1000);
    const timeoutB = setTimeout(() => setVarB(varB + 2), 2000);

    return () => {
      clearTimeout(timeoutA);
      clearTimeout(timeoutB);
    };
  }, [varA, varB]);

  return <span>{varA}, {varB}</span>;
}

El ejemplo anterior está mal escrito. Hay dos temporizadores en la función de efectos secundarios y no hay relación entre ellos. En realidad, son dos efectos secundarios no relacionados y no deben escribirse juntos. La forma correcta de escribirlos es separarlos en dos useEffect().
Ortografía correcta:

function App() {
  const [varA, setVarA] = useState(0);
  const [varB, setVarB] = useState(0);

  useEffect(() => {
    const timeout = setTimeout(() => setVarA(varA + 1), 1000);
    return () => clearTimeout(timeout);
  }, [varA]);

  useEffect(() => {
    const timeout = setTimeout(() => setVarB(varB + 2), 2000);

    return () => clearTimeout(timeout);
  }, [varB]);

  return <span>{varA}, {varB}</span>;
}

Resumir:

  • Cuando no hay dependencias, la parte fuera del retorno de la función del primer parámetro de useEffect se ejecutará para la primera carga, y la parte dentro del retorno se ejecutará primero, y luego la parte fuera del retorno se ejecutará cada vez que se actualice.
  • Cuando la dependencia es una matriz vacía ([]), la función del primer parámetro de useEffect se ejecutará cuando la página se cargue por primera vez, similar a ejecutar componentDidMount, y solo se ejecutará una vez, y la función de retorno en la función se ejecutará cuando la página esté a punto de ser destruida o cuando se elimine el componente, similar a ejecutar componentWillUnMount
  • Cuando la dependencia no está vacía, la parte fuera del retorno de la función del primer parámetro de useEffect se ejecutará por primera vez al cargar. Cada vez que se actualice la dependencia, se ejecutará primero la parte dentro del retorno, y luego se ejecutará la parte fuera del retorno.

Es decir, salvo el montaje y desmontaje inicial de componentes, las funciones fuera de retorno y dentro de retorno se ejecutarán por separado, y el resto de funciones se ejecutarán en retorno y luego fuera de retorno.

Enlace original: https://blog.csdn.net/CX345678/article/details/128705404

Supongo que te gusta

Origin blog.csdn.net/BUG_CONQUEROR_LI/article/details/130875148
Recomendado
Clasificación