Tengo esta función useEffect en el componente de reacción. Estoy llamando api videoGridState aquí. Ahora, lo que está sucediendo aquí es llamar a mi api 2 veces una en la recarga de la página inicial y la segunda cuando el conteo está cambiando. Quiero que se llame una sola vez cuando se recarga la página. Pero también cuando streamSearchText cambia
const [count, setCount] = useState(0); const [streamSearchText, setStreamSearchText] = useState(""); useEffect(() => { videoGridState(); }, [count]); useEffect(() => { const delayDebounceFn = setTimeout(() => { setCount(count + 1); }, 1000); return () => clearTimeout(delayDebounceFn); }, [streamSearchText]);¿Cómo puedo hacer eso?
El problema principal es que tiene dos llamadas useEffect , por lo que cada una de ellas se maneja, y la segunda activa la primera (después de un retraso), lo que resulta en la duplicación.
Según tengo entendido, su objetivo es:
videoGridState inmediatamente en el montaje ystreamSearchTextEso resulta ser sorprendentemente incómodo de hacer. Probablemente terminaría usando una referencia para ello:
const firstRef = useRef(true); const [streamSearchText, setStreamSearchText] = useState(""); useEffect(() => { if (firstRef.current) { // Mount videoGridState(); firstRef.current = false; } else { // `streamSearchText` change const timer = setTimeout(() => { videoGridState(); }, 1000); return () => clearTimeout(timer); } }, [streamSearchText]);Ejemplo en vivo:
const { useState, useRef, useEffect } = React; function videoGridState() { console.log("videoGridState ran"); } const Example = () => { const firstRef = useRef(true); const [streamSearchText, setStreamSearchText] = useState(""); useEffect(() => { if (firstRef.current) { // Mount videoGridState(); firstRef.current = false; } else { // `streamSearchText` change const timer = setTimeout(() => { videoGridState(); }, 1000); return () => clearTimeout(timer); } }, [streamSearchText]); return <div> <label> Search text:{" "} <input type="text" value={streamSearchText} onChange={(e) => setStreamSearchText(e.currentTarget.value)} /> </label> </div>; }; const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<Example />); <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script> También podría hacer la consulta inmediatamente cuando streamSearchText es "" , pero eso sucedería cada vez streamSearchText fuera "" , no solo en el montaje. Eso puede ser lo suficientemente bueno, dependiendo de cuán riguroso deba ser.
Además , sin embargo, si todavía ve que algo sucede "en el montaje" dos veces, es posible que esté ejecutando una copia de desarrollo de las bibliotecas con React.StrictMode alrededor de su aplicación (el valor predeterminado en muchos sistemas de andamios). Consulte las respuestas deesta pregunta para obtener detalles sobre cómo React.StrictMode puede montar su componente más de una vez y arrojar otras sorpresas aparentes.
Su siguiente función useEffect() hace que suceda este comportamiento:
useEffect(() => { const delayDebounceFn = setTimeout(() => { setCount(count + 1); }, 1000); return () => clearTimeout(delayDebounceFn); }, [streamSearchText]); Dado que se ejecuta inicialmente pero llamado setCount() que actualiza el estado y fuerza una nueva representación del componente que a su vez ejecuta el primer useEffect() ya que tiene [count] en la matriz de dependencia.
Y por lo tanto, el ciclo continúa para el [count]