Tengo una alerta que quiero ocultar en una función de tiempo de espera después de agregar o eliminar un elemento de una lista.
En lugar de limpiar la función de tiempo de espera, useEffect termina en un bucle.
function App() { const [item, setItem] = useState({ id: "", name: "", }); const [list, setList] = useState([]); const [isEditing, setISEditing] = useState(false); const [alert, setAlert] = useState({ active: false, type: "", }); const addToList = (e) => { e.preventDefault(); setAlert({ active: true, type: "success" }); let newItem = { id: new Date().getTime().toString(), name: item }; e.preventDefault(); setList([...list, newItem]); }; const removeFromList = (id) => { setAlert({ active: true, type: "danger" }); setList(list.filter((item) => item.id !== id)); }; useEffect(() => { const timeout = setTimeout(() => { setAlert({ active: false, type: "" }); }, 3000); return () => clearTimeout(timeout); }, [alert.active]);Tengo un ejemplo similar a continuación, pero useEffect no terminó en un bucle, aunque cambio el estado en useEffect. ¿Cuál es exactamente la diferencia entre los dos?
const SingleColor = ({ rgb, weight, index }) => { const [alert, setAlert] = useState(false); const hex = rgbToHex(...rgb); useEffect(() => { const timeout = setTimeout(() => { setAlert(false); }, 3000); return () => clearTimeout(timeout); }, [alert]); return ( <article className={`color ${index > 10 && "color-light"}`} style={{ backgroundColor: hex }} onClick={() => { setAlert(true); navigator.clipboard.writeText(hex); }} > <p className="percent-value">{weight}%</p> <p className="color-value">{hex}</p> {alert && <p className="alert">Copied to clipboard!</p>} </article> ); }; export default SingleColor;Con la dependencia alert.active le está diciendo que vuelva a activar el useEffect cada vez que alert.active cambie. Y dentro de useEffect está configurando un nuevo valor para alert.active , por lo tanto, creando un bucle infinito.
Debería llamar al tiempo de espera directamente al final de la función addToList o remove from list. Si quieres puedes aislarlo en una función aparte
const cancelTimeout = () => { setTimeout(() => setAlert({ active: false, type: "" }), 3000) } y llame a cancelTimeout al final de AddToList y removeFromList