反应状态返回了不同步的数据

时间:2019-02-25 22:37:24

标签: reactjs react-hooks

我有以下使用React钩子的组件:

import React, {useState} from 'react';

// import components
import TagManagementRow from './TagManagementRow';

const TagManagementList = (props) => {

  const [tagData, setTagData] = useState(props.data);

  const deleteAction = (id) => {
    // Call to backend to delete tag
    const currentData = [];

    for( var i = 0; i <= tagData.length; i++){

      if(i < tagData.length && tagData[i].id !== id) {
        currentData.push(tagData[i]);
      }

      if(i === tagData.length) setTagData(currentData);
    };
  };

  return (
    <ul className="tagManagement">
      {tagData.map( (tag,i) => {
        return <TagManagementRow name={tag.name} key={i} id={tag.id} delete={() => deleteAction(tag.id)} />
      })}
    </ul>
  );
}

export default TagManagementList;

它呈现4个TagManagementRow子组件,每个子组件都有一个删除按钮。当我单击删除按钮时,如果将更改后的状态注销到控制台,一切看起来都会很好,但是,在实际的浏览器中,列表中的最后一项被删除了。我觉得这是某种渲染/定时问题,但似乎无法解决。感谢那些更好地了解钩子的人的任何帮助。

顺便说一下,这是TagManagementRow组件的代码:

import React, { useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

const TagManagementRow = (props) => {

  const [editTag, setEdit] = useState(false);
  const [tagName, setTagName] = useState(props.name);
  const [tempName, setTempName] = useState('');

  const handleEdit = (e) => {
    setTempName(e.target.value);
  };

  const switchToEdit = () => {
    setEdit(!editTag);
  }

  const saveEdit = () => {
    setTagName(tempName);
    setTempName('');
    switchToEdit();

  }

  return (
    <li>
        <span>
          {tagName}
          <FontAwesomeIcon icon={["fas","pen"]} onClick={switchToEdit} />
        </span>

      <span>
        <FontAwesomeIcon icon={["fas","trash-alt"]} onClick={props.delete} />
      </span>
    </li>
  );
}

export default TagManagementRow;

1 个答案:

答案 0 :(得分:1)

您可以使用filter来过滤具有匹配ID的对象,而不是更新循环中的状态。

还要确保将tag.id用作key而不是数组索引,因为在删除元素时,它会改变。

const { useState } = React;

const TagManagementList = props => {
  const [tagData, setTagData] = useState(props.data);

  const deleteAction = id => {
    setTagData(prevTagData => prevTagData.filter(tag => tag.id !== id));
  };

  return (
    <ul className="tagManagement">
      {tagData.map((tag, i) => {
        return (
          <TagManagementRow
            name={tag.name}
            key={tag.id}
            id={tag.id}
            delete={() => deleteAction(tag.id)}
          />
        );
      })}
    </ul>
  );
};

const TagManagementRow = props => {
  const [editTag, setEdit] = useState(false);
  const [tagName, setTagName] = useState(props.name);
  const [tempName, setTempName] = useState("");

  const handleEdit = e => {
    setTempName(e.target.value);
  };

  const switchToEdit = () => {
    setEdit(!editTag);
  };

  const saveEdit = () => {
    setTagName(tempName);
    setTempName("");
    switchToEdit();
  };

  return (
    <li>
      {tagName}
      <button onClick={props.delete}>Delete</button>
    </li>
  );
};

ReactDOM.render(
  <TagManagementList data={[{ id: 1, name: "foo" }, { id: 2, name: "bar" }]} />,
  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"></div>