vivek singh
vivek singh

Reputation: 457

How to change input field value on click

I am developing UI using react ,have two input field On UI, both are having some dynamic value coming from server as JSON data, I am looping the data and showing data on UI.

I have one button on click of which what I want to one of input field data whose id match.

So I am using useEffect on button click and trying to override data but it is not showing new data on UI.

useEffect(() => {
    
      let pData = [
        {
          fname: "test",
          lname: "test1",
          id: 1
        }
      ];

      test.map((li) => {
        if (li.component_id === pData[0].component_id) {
          return { ...li, fname: pData[0].fname };
        }
      });
    
  }, [triggerdata]);

On click I am doing this

    const btnClick = () => {
    setTriggerData(!triggerdata);
  };

Edit/Update

I am getting data from another component as props and setting it to state

let [copmData, setCompData] = useState(props.data);

And in my useEffect

I am doing this

    useEffect(() => {
    let pData = [
      {
        fname: "test",
        lname: "test1",
        id: 1
      }
    ];

    copmData = copmData.map((li) => {
      if (li.id === pData[0].id) {
        return { ...li, fname: pData[0].fname };
      }
      return li;
    });
  }, [triggerdata]);

Updated code sandbox

Upvotes: 0

Views: 515

Answers (1)

Nikita Chayka
Nikita Chayka

Reputation: 2135

Updated your sandbox - https://codesandbox.io/s/intelligent-wood-5th2p

There were multiple problems:

  1. You were creating your test data (test) inside of component - so it will actually always be resetted back to default, so i moved it outside.
  2. Then in map function you were checking property .component_id, which you don't have in testData objects, you should have used .id
  3. test.map - returns new array, so you need to do test = test.map
  4. In map function you were not returning the result if your if statement is not firing - but you should, otherwise you will arrays of undefined
  5. In input you were providing defaultValue, you should have used value instead. defaultValue is not resetting after re-render (hence no update seen)
  6. And minor one - when you are trying to render multiple components from array - you should always specify unique key property.

Final code:

  let test = [ //initializing test data OUTSIDE of component
  {
    fname: "Michel",
    lname: "Clark",
    id: 1
  },

  {
    fname: "Steve",
    lname: "Smith",
    id: 2
  }
];

export default function App() {
   const [triggerdata, setTriggerData] = useState(true);

  useEffect(() => {
    let pData = [
      {
        fname: "test",
        lname: "test1",
        id: 1
      }
    ];

    test = test.map((li) => { //Here i'm setting test to result of mapping
      if (li.id === pData[0].id) { //here you were using .component_id
        return { ...li, fname: pData[0].fname };
      }
      return li; //here you were missing return
    });
  }, [triggerdata]);
  const btnClick = () => {
    setTriggerData(!triggerdata);
  };
  return (
    <div className="App">
      <button onClick={btnClick}>Click</button>
      {test.map((li, index) => (
        <div key={index}> //you didn't provide unique key
          <input value={li.fname} /> //here you were using defaultValue
        </div>
      ))}
    </div>
  );
}

UPDATE

So in your new code you had yet another multiple issues.

  1. When you use state now, you should not directly change it, you should use setter (second value returned from useState), in your case - setCompData
  2. useEffect runs on initial render, so you your update logic is executed "right when" component is mounted, meaning you will have your "test" update immediately, not after you press the buuton, so you need some condition there, i suspect by your logic you would need if(triggerdata)

Sandbox - https://codesandbox.io/s/ecstatic-sanderson-nenrr

Updated part:

useEffect(() => {
if (triggerdata) { //you need if to run your logic only after user click the button
  let pData = [
    {
      fname: "test",
      lname: "test1",
      id: 1
    }
  ];

  setCompData( //use the state setter, not compData = compData.map
    copmData.map((li) => {
      if (li.id === pData[0].id) {
        return { ...li, fname: pData[0].fname };
      }
      return li;
    })
  );
} else {
  setCompData(props.data);
}
}, [triggerdata]);

Upvotes: 4

Related Questions