React钩子-如何正确更新和渲染元素

时间:2020-10-13 20:19:20

标签: javascript reactjs

当我按下删除按钮时,它每次都仅删除最后一个元素,而不管索引如何。 我该怎么做呢?无需在子组件中将<input defaultValue={name} />更改为<input value={name} />,我已经用<input defaultValue={name} />完成了,但是如何使用输入的value属性呢?

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>
  );
});

1 个答案:

答案 0 :(得分:0)

您的代码中有错字(onDeletehandleDelete),但这不是主要问题。您的问题是使用index作为key。由于您要删除附加到状态的某些元素,因此React index不可信任,因此无法决定如何再次对数组排序。

您应该为密钥使用一些唯一的值,如果没有,则应以某种方式创建它们。在下面的示例中,我尝试将index与以下值混合:

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

此外,请勿使用类似splice的方法,因为它们会改变状态。 splice将元素更改到位,因此进行了更改。我使用了filter,但是您可以使用任何其他不会改变状态的方法。

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" />