Home > Enterprise >  REACT: array.map() function not rendering components properly when dealing with an array with newly
REACT: array.map() function not rendering components properly when dealing with an array with newly

Time:09-27

Need help with the REACT code below. Making a note taking app and tried to make it so that a new note appears at the top of the list of my notes. My code works fine when I add the new note at the end of the array, but if I switch it so that when I add it in the beginning like so:

const newNotes = [newNote, ...notes];

it then displays all the same old notes with the last one repeated twice. the code responsible for displaying the notes on the screen looks like this.

  const listNotes = ()=>{
    console.log(notes);
    return notes.map((obj, index) => (
      <Note
        key={index}
        id={obj.id}
        subject={obj.subject}
        text={obj.text}
        date={obj.date}
        handleDeleteNote={deleteNote}
      />
    ))
  }

After some debugging I notice that the new list is being created successfully and the map is creating the notes components "successfully" and when I print notes to the console right before the map function it seems to show that the the newly created list is fine. but when it gets to the ".map()" for some reason it's not following the list exactly, it's almost like it doesn't realize there's a new item in the list until it's halfway through redering the notes.

full code of component below.

import React, { useState, useEffect } from "react";
import { nanoid } from "nanoid"; //allows for random IDs
import NoteSearch from "./NoteSearch"; // component that searches notes
import Note from "./Note"; // Component for saved notes 
import AddNewNote from "./AddNewNote"; //Component to add new note

const NotesList = () => {
  // States
  const [notes, setNotes] = useState([
    {
      id: nanoid(),
      subject: "Fruit",
      text: "bananas are awesome",
      date: "9/23/2022",
    },
    {
      id: nanoid(),
      subject: "ew",
      text: "onions are awesome",
      date: "9/24/2022",
    },
    {
      id: nanoid(),
      subject: "veggie",
      text: "carrots are awesome",
      date: "9/25/2022",
    },
  ]);

  // Add and Delete Note handlers
  const addNote = (subject, text) => {
    const date = new Date();
    const newNote = {
      id: nanoid(),
      subject: subject,
      text: text,
      date: date.toLocaleDateString(),
    };
    const newNotes = [newNote, ...notes];
    setNotes(newNotes);
  };
  const deleteNote = (CurrentID) => {
    const newNotes = notes.filter((note)=>note.id !== CurrentID);
    setNotes(newNotes);
  };

//functions 
  const listNotes = ()=>{
    console.log(notes);
    return notes.map((obj, index) => (
      <Note
        key={index}
        id={obj.id}
        subject={obj.subject}
        text={obj.text}
        date={obj.date}
        handleDeleteNote={deleteNote}
      />
    ))
  }

  // This is the notes app DOM
  return (
    <div className="notes-wrapper">
      <NoteSearch />
      <div className="all-notes">
        <AddNewNote handleAddNote={addNote}/>
        {
          listNotes()
        }
      </div>
    </div>
  );
};

CodePudding user response:

Use id as key not index:

   <Note
    key={obj.id}
    id={obj.id}
    subject={obj.subject}
    text={obj.text}
    date={obj.date}
    handleDeleteNote={deleteNote}
  />

You are changing your list dynamically and it is discouraged to use index as key and may cause an issue.

React doc.: We don’t recommend using indexes for keys if the order of items may change.

CodePudding user response:

This is because you are using indexes as keys. React thinks that you don't want to unmount/remount the n first nodes (those that were already existing). It will just update their props. Likely your Node component initializes its state in the constructor or after the component did mount and do not recompute the state on props changes. As a consequence the list is not updated visually, except for the last new node.

Using the id as key should solve the problem.

  • Related