简体   繁体   中英

React hooks - How to update and render elements properly

When I press delete button, it only deletes the last element every time, regardless to index. How can I do this proper way? Without changing <input defaultValue={name} /> to <input value={name} /> in Child component?, I've done it with <input defaultValue={name} /> , but how could I do this with value property to an input?

export const App = () => {
  const [names, setNames] = React.useState([
    "First",
    "Second",
    "third",
    "fourth",
  ]);
  const onChange = (params) => {
    doing(params); // etc.
  };
  function onDelete(index: number) {
    const nameArr = [...names];
    nameArr.splice(index, 1);
    setNames(nameArr);
  }
  return (
    <div>
      {names.map((name, index) => (
        <ChildComponent
          key={index}
          name={name}
          index={index}
          onChange={onChange}
          onDelete={handleDelete}
        />
      ))}
    </div>
  );
};

const ChildComponent = React.memo(({ name, index, onChange, onDelete }) => {
  return (
    <div>
      <input
        defaultValue={name}
        onChange={(event) => onChange(index, event.target.value)}
      />
      <button onClick={() => onDelete(index)}>delete</button>
    </div>
  );
});

You have a typo in your code ( onDelete and handleDelete ) but this is not the main issue. Your problem is using index as your key . Since you are removing some elements attached to the state, React can't decide how to sort the array again, because index here is not trustable.

You should use some unique values for your keys, if there is not, you should create them somehow. In the below example I try to mix index with the value:

key={`${index}${name}`}

Also, do not use methods like splice since they mutate the state. splice change elements in place, so mutation. I used filter but you can use any other method which doesn't mutate the state.

 function App() { const [names, setNames] = React.useState([ "First", "Second", "third", "fourth" ]); function onDelete(index) { setNames((prev) => prev.filter((_, i) => i !== index)); } return ( <div> {names.map((name, index) => ( <ChildComponent key={`${index}${name}`} name={name} index={index} onDelete={onDelete} /> ))} </div> ); } const ChildComponent = React.memo(({ name, index, onChange, onDelete }) => { return ( <div> <input defaultValue={name} onChange={(event) => onChange(index, event.target.value)} /> <button onClick={() => onDelete(index)}>delete</button> </div> ); }); ReactDOM.render( <App />, document.getElementById("root") );
 <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM