Intento crear un gancho personalizado para validar mis entradas. Pero si el enlace personalizado devuelve un objeto, se vuelve a crear en cada cambio en la página
const useInput = (initialValue) => { const [value, setValue] = useState(initialValue) const [state, setState] = useState('') return {value, state} } const user = useInput('')De esa manera puedo obtener valores usando
user.value user.statePero si hay varias entradas en la página, una entrada desencadena la recreación de todas las demás entradas.
useEffect(() => { console.log('This triggers on every change on the page') }, [user])Pero si lo destruyo primero así, entonces todo está bien.
const {userValue, userState} = useInput('') useEffect(() => { console.log('Does not trigger on other inputs') }, [userValue, userState])O si devuelvo el objeto usando useMemo, también funciona bien:
const useInput = (initialValue) => { const [value, setValue] = useState(initialValue) const [state, setState] = useState('') const obj = useMemo(() => { return {value, state} }, [value, state]) return obj } const user = useInput('')¿Cuál es la razón de esto, por qué el objeto 'usuario' cambia incluso si no hubo cambios en él y usa useState en los valores? ¿Por qué deja de volver a crear después de destruir o usar useMemo?
Soy nuevo en React y trato de entenderlo.
Cada vez que llama a useInput , está creando un nuevo objeto con la sintaxis literal de objeto {} y luego devolviéndolo y almacenándolo en user . Debido a que es un objeto nuevo, es una referencia nueva en la memoria, por lo que no se considera igual al último objeto de user (ya que los objetos se comparan por referencia). Como resultado, su devolución de llamada useEffect() activa. Sin embargo, cuando usa useMemo() , devolverá la misma referencia de objeto si el value o state no han cambiado, por lo que no se crea un nuevo objeto si el value y el state siguen siendo los mismos, y en su lugar se reutiliza el objeto anterior.
La desestructuración funciona porque cuando desestructura sus valores de su objeto, está extrayendo los valores de cadena primitivos en variables. Como las cadenas son primitivas, se comparan por valor, a diferencia de los objetos que se comparan por su referencia. Como los valores de sus cadenas desestructuradas en su matriz de dependencias son iguales a los del último renderizado, su useEffect() no activará la devolución de llamada.
Consulte el fragmento de código a continuación para obtener más detalles:
const foo = () => { // similar to your `useInput()` function // These behave like your state values const a = "a"; const b = "b"; return {a, b}; } // --- Let's try and use objects --- // First render const obj1 = foo(); // on each render, you call `userInput()` // Second render const obj2 = foo(); // `userInput()` called again, this creates a complelty new object in memory that is different to `obj1` console.log("Is obj1 equal to obj2?", obj1 === obj2); // false - React compares the prev object reference to the current to decide if it should call the useEffect() callback, since they're not equal, react calls the callback // --- Let's try and pull out the values --- // First render const {a, b} = foo(); // `a` and `b` are string values (primitives) // Second render (using aliasing with destructuring to avoid naming conflicts) const {a:a2, b:b2} = foo(); console.log("Is a and b from the first render equal to a2 and b2 from the second?:", a === a2 && b === b2); // true - Since a2 is equal to a from the first "render", and b is equal to b2, React doesn't call the callback