Estoy tratando de evitar modificar el estado directamente, así que estoy usando lodash cloneDeep() y luego establezco el estado usando el clon. Sin embargo, quiero realizar cambios adicionales (después de una solicitud asíncrona) y establecer el estado nuevamente. Después de pasar mi clon a la función set, ¿está fuera de los límites continuar haciendo cambios en ese clon? ¿Necesito volver a clonar mi clon para estar seguro o React hace un clon de mi clon? El código puede ayudar a explicar el problema:
const [user, setUser] = useState({ name: '', email: '' }) const newUser = cloneDeep(user) // cloning to avoid modifying state directly newUser.name = 'Steve' // setting a property on the clone setUser(newUser) // all good up to this point // some async stuff happens, then later: newUser.email = 'steve@example.com' // still modifying the clone, but is this safe? setUser(newUser)Dado que modifiqué el clon que pasé anteriormente con setUser, ¿eso solo modificó el estado directamente?
Traté de inspeccionar el código fuente de React para determinar si estaban haciendo un clon cuando llamé a setUser() pero no pude comprender lo que estaba pasando. :)
newUser.email = 'steve@example.com' // still modifying the clone, but is this safe? setUser(newUser) No creo que esta sea una buena idea. newUser es la misma referencia que usó en la llamada anterior a setUser (antes de la solicitud asíncrona), por lo que reaccionar puede setState porque es el mismo valor que usó durante la llamada anterior a setState .
También tu situación es la misma que esta.
let user = {}; setUser(user); user.a=1; en el siguiente sentido: una vez que paso user a setUser en el paso 2, no importa si es un objeto nuevo o algo que cloné antes, el punto está en el paso 3. Estoy modificando algo que pasé a setUser en el paso 2 . Y esto me parece modificar algo que está en estado.
Así que intente actualizar el estado de forma inmutable la segunda vez también. La mayoría de las veces, hacer actualizaciones de estado inmutables con copia superficial usando ... me ha funcionado (si lo hace bien), por lo que podría evitar una biblioteca adicional.
Yo simplificaría esto:
const [user, setUser] = useState({ name: '', email: '' }) // spread and create a new object // and append the new property const newUser = { …user, name: “Steve” } setUser(newUser) // Async call happens // spread and create a new object // and append the new property setUser({ …newUser, email: “steve@example.com” })Todo lo que se necesita es usar el operador de propagación.
No estoy seguro de cuáles son las razones para configurar el nombre primero y luego el emsil, pero ¿por qué no hacer la llamada primero y configurar el usuario por completo? No tendrás que preocuparte por nada de lo anterior de esa manera. También guardará un ciclo de renderizado.