Reaccionar arroja un error cuando intentamos actualizar el estado en un componente desmontado. Entonces, cuando pruebo el componente de reacción para eso, obtengo errores solo en el primer renderizado.
Hice un componente que habilita el componente secundario en función del clic. Y el componente secundario tiene un botón que actualiza el estado después de un tiempo de espera establecido que arroja una advertencia de reacción
Advertencia: no se puede realizar una actualización de estado de React en un componente desmontado. Esto no es operativo, pero indica una pérdida de memoria en su aplicación. Para solucionarlo, cancele todas las suscripciones y tareas asincrónicas en una función de limpieza useEffect.
Lo cual es perfectamente válido. Pero para superar esto, paso habilitar accesorios del componente principal en función de que existe una condición justo antes de establecer el tiempo de espera en el componente secundario. Entonces, ¿por qué arroja un error solo la primera vez?
Reproducir
Haga clic en el botón del componente secundario que es false y haga clic en el botón del componente principal enable desmonta el componente secundario.
** Mi pregunta es ¿por qué reaccionar arroja un error solo la primera vez? Y por qué funciona bien la segunda vez **
Componente principal
import { useState } from "react"; import "./styles.css"; import { Test } from "./Test"; export default function App() { const [state, setstate] = useState(true); const changeState = () => { setstate(!state); }; return ( <div className="App"> <button onClick={changeState}>enable </button> {state && <Test enable={state} />} </div> ); }Componente hijo
import React, { useState } from "react"; export const Test = (props) => { const [state, setstate] = useState(false); const fetchData = () => { setstate(!state); if (props.enable) { setTimeout(() => { setstate(false); }, 1000); } }; return ( <> <button onClick={fetchData}> {`${state}`}</button> </> ); };Buena pista, solo te falta un punto menor, cuando escribes un estado que necesita algo de tiempo para ejecutarse y al mismo tiempo podemos visitar el flujo una y otra vez en función de cualquier acción, entonces necesitamos borrar la suscripción anterior antes de ir a la nueva una...
Por ejemplo, en su código aquí, actualiza el flujo de estado, pero el flujo de estado registra una nueva suscripción cada vez que visitamos un componente con accesorios válidos y hacemos clic en el botón, de modo que la ejecución anterior aún puede funcionar cuando activa un nuevo evento, así que simplemente, lo que tenemos que hacer es desmontar la suscripción anterior y podemos hacerlo con esto para su caso:
import React, { useState, useEffect } from "react"; export const Test = (props) => { const [state, setstate] = useState(false); useEffect(() => { if (props.enable) { const timer = setTimeout(() => { setstate(false); }, 1000); return () => clearTimeout(timer); } }, [state, props.enable]); const fetchData = () => { setstate((prev) => !prev); }; return ( <> <button onClick={fetchData}> {`${state}`}</button> </> ); };Mire el código anterior, simplemente agregamos el código necesario para la limpieza en efecto, que se ve en mi estado y apoyo, ahora cuando hago clic en el botón, el efecto se activará, si lo hacemos nuevamente, clearTime funcionará para la suscripción anterior y luego añadir uno nuevo y así sucesivamente...
Notas:
const fetchData = useCAllback...setstate((prev) => !prev); funcionará como una instantánea, y será útil cuando dependa de un valor antiguo... pero puede que no sea necesario en algunos casos también, sino solo para conocer esta función.Qué es la suscripción:
Puede decir que la suscripción representa un recurso desechable, como la ejecución de un Observable. Una suscripción tiene un método importante, darse de baja, que no acepta argumentos y simplemente desecha el recurso que tiene la suscripción; en otras palabras, puede decir que sí, se invocará cualquier tarea asíncrona o cualquier trabajo para reaccionar al estado del ciclo de vida y es necesario para observar los cambios, luego habla de suscripción, como API o tiempo de espera o intervalo de tiempo, etc., cualquiera de estas acciones debe borrar la suscripción previa (detener observador - cancelar suscripción) para evitar cualquier pérdida de memoria y borrar la memoria para mantener el flujo de estado seguro y evita el enrojecimiento innecesario.