Skip to content

React controlled component unable to set on change text input

This a small functional component. A list is rendered in a input. Tried changing the key but it dint worked. I am having issues in reflecting Input text changes.

import { useState } from "react";
import "./styles.css";

export default function App() {
  const [list, setList] = useState([
    { id: 1, text: "abc" },
    { id: 1, text: "zxy" }
  ]);

  const setText = (e, id) => {
    setList((old) => {
      old[id].text = e.target.value;
      console.log(old)
      return old;
    });
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Edit to see some magic happen!</h2>
      {list.map((li, index) => (
        <input
          key={index}
          value={li.text}
          onChange={(e) => setText(e, index)}
        />
      ))}
    </div>
  );
}

const { useState } = React;

function App() {
  const [list, setList] = useState([
    { id: 1, text: "abc" },
    { id: 1, text: "zxy" }
  ]);

  const setText = (e, id) => {
    setList((old) => {
      old[id].text = e.target.value;
      console.log(old)
      return old;
    });
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Edit to see some magic happen!</h2>
      {list.map((li, index) => (
        <input
          key={index}
          value={li.text}
          onChange={(e) => setText(e, index)}
        />
      ))}
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector("#app-container"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<div id="app-container"></div>

Answer

In such case, You need to update your list field(text) based on typed matched object by Id or other unique field.

export default function App() {
  const [list, setList] = useState([
    { id: 1, text: "" },
    { id: 1, text: "" }
  ]);

  const setText = (e, id) => {
    const { value } = e.target;
    setList((lists) => lists?.map((list, index) =>
        index === id ? { ...list, text: value } : list
      ));
  };
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Edit to see some magic happen!</h2>
      {list.map((li, index) => (
        <input
          key={index}
          value={li.text}
          onChange={(e) => setText(e, index)}
        />
      ))}
    </div>
  );
}

Live demo