Me he enfrentado a este problema durante un par de días en los que tengo una matriz llamada tempTaskArray, que almacena objetos llenos de datos tomados de mi base de datos de Firestore.
Estos objetos contienen los datos correctos en cada iteración del método .forEach, pero cuando se colocan en mi variable de estado, "tareas" (una matriz), de la matriz tempTaskArray, todos los objetos contienen los datos del último objeto creado.
Este problema no se encuentra cuando tengo una matriz de cadenas.
Vea el código a continuación:
const getTasks = () => { db.collection("users").doc(uid).collection("tasks") .orderBy("epochdate", "asc") .get() .then((querySnapshot) => { querySnapshot.forEach((doc) => { // populates array with strings // tempTaskArray.push(doc.data().taskname) // tempTaskObject is an empty object tempTaskObject.taskname= doc.data().taskname tempTaskObject.duedate= doc.data().duedate // gets epoch date value and stores it var epochDate = doc.data().epochdate; // gets current time const day = new Date(); let currentTime = day.getTime(); // finds time remaining in epoch var timeRemaining = epochDate - currentTime; // finds how many days are left and rounds down var daysLeft = (timeRemaining / 86400000) daysLeft = Math.floor(daysLeft) tempTaskObject.duein = daysLeft tempTaskArray.push(tempTaskObject) }); setTasks(tempTaskArray) }) .catch((error) => { console.log("Error getting documents: ", error); }); } getTasks();Los datos tomados que completan la variable de estado "tarea" se procesan en el componente Tarea que se ve a continuación:
<div> {tasks.map((task) => ( <Task key={task} task__title={task.taskname} due__date={task.duedate} days__away={task.duein} /> ))} </div>Estaría muy agradecido por una explicación de por qué está sucediendo esto. Gracias por adelantado
Según el código proporcionado, creo que es un error agregar la referencia de tempTaskObject a tempTaskArray y cambiar el mismo objeto al que se hace referencia en cada iteración.
Para evitar esto, puede reasignar un nuevo Objeto a tempTaskObject en cada iteración, como
.then((querySnapshot) => { querySnapshot.forEach((doc) => { // tempTaskObject is (now really) an empty object tempTaskObject = {}; tempTaskObject.taskname= doc.data().taskname;Explicación adicional
Creo que funcionó antes con los tipos de cadena, porque estos son tipos de datos primitivos que simplemente se copiarán en tempTaskArray .
Sin embargo, el tempTaskObject actual tiene varias propiedades (duein, taskname, duedate) y, por lo tanto, es un objeto complejo. Al empujar objetos a una matriz de JavaScript, agrega la referencia al objeto a la matriz, NO una copia . En su ejemplo, siempre mantiene la referencia a tempTaskObject y es por eso que siempre cambia las propiedades del mismo objeto exacto.
Ejemplos
// Array with Primitives const animalNames = ['Tiger', 'Spider']; console.log('animalNames', animalNames); let scaryName = animalNames[1]; scaryName = 'Goldfish'; console.log('still scary animalNames', JSON.stringify(animalNames)); // nothing changed, because we're working with a copy // Array with Objects const animals = [{ name: 'Tiger', teeth: 30, legs: 4 }, { name: 'Spider', teeth: 0, legs: 8 }]; console.log('animals', animals); let scaryAnimal = animals[1]; // storing a reference to the spider object scaryAnimal.name = 'Goldfish'; scaryAnimal.legs = 0; console.log('less scary animals', animals); // spider got replaced by a goldfish // Now we'll want to add another animal the WRONG WAY // FIX: Uncomment line below to properly add a bunny // scaryAnimal = {}; scaryAnimal.name = 'Bunny'; scaryAnimal.legs = 4; scaryAnimal.teeth = 2; animals.push(scaryAnimal); console.log('duplicated animal', JSON.stringify(animals));Editar: error tipográfico fijo