Lo que sé es que useState no se volverá a renderizar si pasamos el mismo estado, y lo pruebo yo mismo, pero funcionó solo la primera vez que se volvió a renderizar el componente, con un estado inicial pasado a useState. Pero en el ejemplo a continuación, useState vuelve a representar el componente incluso si paso la misma referencia, también useEffect sabe que el estado no cambió. La imagen con console.logs muestra ese comportamiento.
const arr = [ { name: 'Khaled', id: 0 }, { name: 'Mohamed', id: 1 }, { name: 'Ahmed', id: 2 }, { name: 'Mohsen', id: 3 }, ]; function App() { console.log('num $1'); const [same, setSame] = useState({}); useEffect(() => { console.log('num $3'); const test = arr.find((el) => el.id === 0); console.log(Object.is(same, test)); setSame(test); }, [same]); console.log('num $2'); return <div>welcome</div>; }
El componente se representa dos veces porque tiene el valor inicial para el mismo estado que está vacío { }. dentro de useEffect, actualiza este estado con un nuevo objeto, luego useEffect activa un nuevo valor que se ha agregado al mismo estado. que es el objeto coincidente de su matriz. luego, el componente se volvió a renderizar y es por eso que ingresó a la consola. Registre el valor verdadero.
const arr = [ { name: 'Khaled', id: 0 }, { name: 'Mohamed', id: 1 }, { name: 'Ahmed', id: 2 }, { name: 'Mohsen', id: 3 }, ]; function App() { console.log('num $1'); const [same, setSame] = useState({}); <= initial value useEffect(() => { console.log('num $3'); const test = arr.find((el) => el.id === 0); console.log(Object.is(same, test)); <= changed from false to true because the new value of same setSame(test); <= you updated the state }, [same]); <= the value of same changed from { } to a new value and that's make the component to re-render console.log('num $2'); return <div>welcome</div>; }
Esa es una actualización de tu último comentario.
import { useState, useEffect } from "react"; const arr = [ { name: "Khaled", id: 0 }, { name: "Mohamed", id: 1 }, { name: "Ahmed", id: 2 }, { name: "Mohsen", id: 3 } ]; export default function App() { const [same, setSame] = useState(arr); useEffect(() => { const test = arr.find((el) => el.id === 0); console.log(same); <= here the same is [] with 4 objecs setSame(test); console.log(same); <= here the same is { } }, [same]); return <div>welcome</div>; }
con ese. esto nos llevará a que el useEffect una vez que vea el mismo se actualice. luego volverá a renderizar el componente como mencioné antes.
aquí mismo tienen los mismos datos. pero son diferentes porque el primero es igual [] y el segundo es { }. así que eso es un cambio en el estado. entonces useEffect volverá a renderizar.
La respuesta anterior lo explica perfectamente. Para no volver a renderizar el estado, debe inicializarlo con la matriz original.
const arr = [ { name: 'Khaled', id: 0 }, { name: 'Mohamed', id: 1 }, { name: 'Ahmed', id: 2 }, { name: 'Mohsen', id: 3 }, ]; function App() { console.log('num $1'); const [same, setSame] = useState(arr); <= initial value is now original arr useEffect(() => { console.log('num $3'); const test = arr.find((el) => el.id === 0); console.log(Object.is(same, test)); <= changed from false to true because the new value of same setSame(test); <= you updated the state }, [same]); <= the value of same changed from { } to a new value console.log('num $2'); return <div>welcome</div>; }
Tenga en cuenta que esto solo funciona para los tipos de referencia. Hook no realiza una comparación de objetos o matrices, simplemente verifica si la referencia cambia o no. Esto no funciona para los tipos de valor.
Estoy un poco confundido sobre qué es exactamente lo que está tratando de hacer, pero aquí está mi comprensión de esto y, con suerte, una respuesta a su problema.
Es importante recordar que se llamará a useEffect()
en el montaje del componente (primer renderizado) sin importar qué. Esta es la razón por la que su componente escupe el registro de la consola num $3
en el primer renderizado, aunque lógicamente esperaría que no se ejecutara en absoluto, ya que la única función setSame()
está dentro del useEffect()
.
Debido a que el componente se vuelve a representar después de que el estado se establece con un objeto aparentemente idéntico, otra cosa importante para recordar aquí (y con JavaScript en general) es la igualdad referencial . Considera lo siguiente:
{} === {} //false
Aunque lógicamente, esperaría que dos objetos idénticos se evalúen como dos iguales, en lo que respecta a JavaScript, no son lo mismo. Entonces, cuando pasa un objeto a la función setSame()
que se ve igual que el same
estado en ese momento, JavaScript lo considera un cambio de estado y solicita una nueva representación en React.
Espero que esto ayude.