Home > Software engineering >  In React, how to add key value to one object in array of objects
In React, how to add key value to one object in array of objects

Time:04-30

I'm new to React so please bear with me. currently working on a project and currently stuck at the last part. Per project requirement. I'm to fetch data array from an api. display each object's data on the page. and give every object an input element to be able to add a tag, display tag with the data. then be able to search based on the tag.

a simple version of the data is something like:

[{
    id: "1",
    name: "aaa",
    info: "xxx"
},{
    id: "2",
    name: "bbb",
    info: "yyy"
},{
    id: "3",
    name: "ccc",
    info: "zzz"
}]

i first created a newdata array when i fetch data, and added empty string for tags key.

useEffect(()=>{
  axios.get(apiurl)
    .then(response=>{
        const students = response.data.students;
        const newdata = students.map((o)=>({
                ...o,
                tags: []
            }))
        setNewdata(newdata)
    })
},[apiurl])

so now newdata is like:

    {
        id: "4",
        name: "ddd",
        info: "xyz",
        tags: []
    }

I'm rendering the data array using the .map() and displaying each Object(student) and displaying all the data which includes the input area to add the tags. below is the part of code that displays the tags and input box that allows users to enter tags:

newdata.map(function(student, index){ 
  return(

...//other code before this

<div className="tagbox">
    <div className='tags'>
        {student.tags.map(function(tag, index){
            return <span key={index}>{tag}</span>
        })}
    </div>
    <input 
        id={student.id}
        type="text" 
        placeholder='tag'
        value={newtag}
        onChange={e=> setNewtag(e.target.value)}
        onKeyDown={handleKeyDown} />
</div>
)}

so basically i'm running a handlekeydown function for the enter key. so when the user finishes typing and hits enter. a new tag should display above and have it's value added to the newdata array so i can later match for the search function. problem is I'm unable to figure out the correct code and syntax to execute this logic. So Far all i can come up with is this:

function handleKeyDown(e){
    if (e.key === "Enter"){            
        for (let i = 0; i < newdata.length; i  ){                
            if (newdata[i].id == "1"){
                newdata[i].tags.push(newtag);
            }
        }
        
        setNewtag(''); //this is to empty the input field
    }
}

as you can see, I'm trying to loop through every object (student) in the data. and when the student id matches. we add the data. else we skip. I've hard coded the value to make it work only on the first student. I've tried many methods but i either add to all or add to none.

now I've also been able to add an id to each of the input fields in the jsx like so:

<input id={student.id}/>

now, every input field has a unique id identical to the student's id from the data that's displayed above.

So the question is how should I change my handlekeydown function so that every time i enter a tag it only adds to the data with the same id. PS: every object (student) that's displayed has its own input element from my .map() rendering.

   //my goal is to type "!@#" into the input#4, hit enter and have
    {
        id: "4",
        name: "ddd",
        info: "xyz",
        tags: ["!@#"]
    }

CodePudding user response:

you are only rendering 1 input. Use the same approach to render 1 input for each student like you did for the span

<div className='tags'>
    {student.tags.map(function(tag, index){
        return <span key={index}>{tag}</span>
    })}
</div>
<div>
    {student.map(function(stud, idx){
      return <input 
          id={stud.id}
          key={idx}
          type="text" 
          placeholder='tag'
          value={newtag}
          onChange={e=> setNewtag(e.target.value)}
          onKeyDown={(e) => handleKeyDown(e, stud.id)} />
    })}
<div>

Also remember to update your handleKeyDown function by adding the student id to the signature and use it properly when needed

function handleKeyDown(e, studentId){
    if (e.key === "Enter"){            
        for (let i = 0; i < newdata.length; i  ){                
            if (newdata[i].id == studentId){
                newdata[i].tags.push(newtag);
            }
        }
        
        setNewtag(''); //this is to empty the input field
    }
}

You'll find out there's another issue, in fact all your input are using the same newTag variable. I'll leave that to you :)

  • Related