Search code examples
reactjs

React map using Objects.entries for rendering inputs dynamically and change values of individual fields


I am trying to dynamically render over 100 inputs with preset values using react hooks these values will need to be editable.

I need to map out the inputs using both keys and values.

Currently my code renders all inputs and I can change the values of each individual input, but when I update the value of one input the value of all keys get changed.

below is my code

import React from 'react'

export default function test() {
 const [exampleState, setExampleState]  = React.useState([{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
}]);

const handleChange1 = (e, id) => {
  
  var result = Object.entries(exampleState);
  result = result.map(([key, subject], i)=>{
  if (key === id) subject = e.target.value 
  key = id
  return [key, subject];
  })
 
  setExampleState(result)
  }
  return (
    <div>
         <form>
      {Object.entries(exampleState).map(([key, subject], i) => {
        return (
         
      <label key={i}>{key} 
         <br/>
          <input 
          key={i}
          type="text"  
          id= {key}
        value={subject}  
        onChange={(e) => handleChange1(e, key)} />
       </label>
        );
      })}
      </form>
    </div>
  )
}

on change the value of exampleState changes to something like this

{
 "0": "value1",
    "1": "value2",
    "2": "value3"
}

Solution

    1. Your state should be an object not an array.(I think you missed it when you were typing the question)

    So replace this:

    const [exampleState, setExampleState]  = useState([{
      "key1": "value1",
      "key2": "value2",
      "key3": "value3"
    }]);
    

    With this:

    const [exampleState, setExampleState]  = useState({
      "key1": "value1",
      "key2": "value2",
      "key3": "value3"
    });
    
    1. Simply update your value of the selected key instead of looping through all entries.

    So hope it helps:

    export function Test() {
      const [exampleState, setExampleState]  = useState({
        "key1": "value1",
        "key2": "value2",
        "key3": "value3"
      });
    
      const handleChange = (event, key) => {
        const newExampleState = {...exampleState};
        newExampleState[key] = event.target.value;
        setExampleState(newExampleState);
      }
    
      useEffect(() => {
        console.log(exampleState);
      }, [exampleState])
    
      return (
        <div>
          <form>
            {
              Object.entries(exampleState).map(([key, subject], i) => {
                return (
                  <label key={i}>{key} 
                    <br/>
                    <input key={i} type="text" id= {key} value={subject} onChange={(e) => handleChange(e, key)} />
                  </label>
                );
              })
            }
          </form>
        </div>
      )
    }