React:删除目标表行总是删除第一行

时间:2019-04-04 07:06:27

标签: reactjs

我有一个组件,可以根据在搜索框中输入的字词对公司进行过滤,然后根据其帐户是否已激活来再次对它们进行过滤,然后将它们映射到包含几列公司数据的表格中。每个公司的最后一个表格列均包含几个按钮,其中一个是触发模式对话框的删除按钮,然后必须确认删除或从模式中取消删除。

为简洁起见,我将忽略不重要的进出口:

import {searchingFor} from '../../../containers/CompaniesContainer/CompaniesContainer';
const companiesTable = (props) => {
  return (
    <table className={classes.Table}>
      <thead>
        <tr>
          <th className={classes.First}>&nbsp;</th>
          <th onClick={props.sortByName} className={[classes.Second, props.sortingClass].join(' ')}><span>Name</span><img src={downArrow} alt="down-arrow" /></th>
          <th onClick={props.sortByAddress} className={[classes.Third, props.sortingClass].join(' ')}><span>Email address</span><img src={downArrow} alt="down-arrow" /></th>
          <th onClick={props.sortByAdded} className={[classes.Fourth, props.sortingClass].join(' ')}><span>Added</span><img src={downArrow} alt="down-arrow" /></th>
          <th className={classes.Last}>&nbsp;</th>
        </tr>
      </thead>
      <tbody>
        {
          props.companies.filter(searchingFor(props.term)).filter(function (company) {
            if(props.isActive === true) {
              return company.active;
            } else {
              return !company.active
            }
          }).map((item, index) =>
            <tr key={item.id}>
              <td>
                <img src={companyImg} alt="companies" />
              </td>
              <td>{item.name}</td>
              <td>{item.street},<br/>{item.city}</td>
              <td>{item.added}</td>
              <td>
                <Button btnType={props.btnClass1} onClick={() => props.deleteInitiate(item.name)}>{props.btnText1}</Button>
                <Button btnType={props.btnClass2}>{props.btnText2}</Button>
                <Button btnType={props.btnClass3}>{props.btnText3}</Button>
              </td>
            </tr>
          )
        }
      </tbody>
    </table>
  );
};

export default companiesTable;

然后将该组件从包含两个选项卡的组件中装入两次。在一个标签中,我列出了活动帐户,在另一个标签中,列出了不活动帐户。

const companiesTabs = (props) => {
  return (
    <Tabs tabsClass={classes.TabList} tabContentClass={classes.TabContent}>
      <div 
        label="Active"
        tabClass={classes.TabItem} 
        activeClass={classes.TabItemActive} 
        hasLabel={true}
        hasImg={false}  
      >
        <CompaniesTable 
          isActive={true} 
          term={props.term}
          companies={props.companies}
          sortByName={props.sortByName}
          sortByAddress={props.sortByAddress}
          sortByAdded={props.sortByAdded}
          sortingClass={props.sortingClass}
          toggleSortingClass={props.toggleSortingClass}
          btnClass1="secondary"
          btnClass2="primary"
          btnClass3="success"
          btnText1="Delete"
          btnText2="Deactivate"
          btnText3="Sign in"
          deleteInitiate={props.deleteInitiate}
        />
      </div>
      <div 
        label="Inactive"
        tabClass={classes.TabItem} 
        activeClass={classes.TabItemActive}
        hasLabel={true}
        hasImg={false}
      >
        <CompaniesTable 
          isActive={false} 
          term={props.term}
          companies={props.companies}
          sortByName={props.sortByName}
          sortByAddress={props.sortByAddress}
          sortByAdded={props.sortByAdded}
          sortingClass={props.sortingClass}
          toggleSortingClass={props.toggleSortingClass}
          btnClass1="secondary"
          btnClass2="activate"
          btnClass3="success"
          btnText1="Delete"
          btnText2="Activate"
          btnText3="Sign in"
          deleteInitiate={props.deleteInitiate}
        />
      </div>
    </Tabs>
  );
};

export default companiesTabs;

然后我有一个包含选项卡组件的组件:

const companies = (props) => {
  return (
    <React.Fragment>
      <CompaniesTabs
        term={props.term}
        companies={props.companies}
        sortByName={props.sortByName}
        sortByAddress={props.sortByAddress}
        sortByAdded={props.sortByAdded}
        sortingClass={props.sortingClass}
        toggleSortingClass={props.toggleSortingClass}
        deleteInitiate={props.deleteInitiate}
      />
    </React.Fragment>
  );
};

还有一个基于类的容器组件,其中包含状态和方法,并呈现ModalSearchBoxCompanies组件。

export function searchingFor(term) {
  return function(x) {
    return x.name.toLowerCase().includes(term.toLowerCase()) || !term;
  }
}

class CompaniesContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      term: '',
      sorting: false,
      deleting: false,
      deletingCompanyName: null,
      companies: [
        { 
          id: 1,
          name: "Company 1",
          street: "123 Some Street",
          city: "London",
          added: "03.04.19",
          active: true,
        },
        { 
          id: 2,
          name: "Company 2",
          street: "321 Some other Street",
          city: "New York",
          added: "04.04.19",
          active: false,
        }
      ]
    }
    this.compareBy.bind(this);
    this.sortBy.bind(this);
    this.toggleSortingClass= this.toggleSortingClass.bind(this);
    this.searchHandler = this.searchHandler.bind(this);
    this.deleteInitiateHandler = this.deleteInitiateHandler.bind(this);
  }

  compareBy(key) {
    return function (a, b) {
      if (a[key] < b[key]) return -1;
      if (a[key] > b[key]) return 1;
      return 0;
    };
  }

  sortBy(key) {
    let arrayCopy = [...this.state.companies];
    arrayCopy.sort(this.compareBy(key));
    this.setState({companies: arrayCopy});
  }

  toggleSortingClass() {

  };

  searchHandler(event){
    this.setState({term: event.target.value});
  }

  deleteInitiateHandler = (name) => {
    this.setState({deleting: true, deletingCompanyName: name});
  }

  deleteHandler = (companyIndex) => {
    const companies = [...this.state.companies];
    companies.splice(companyIndex, 1);
    this.setState({companies: companies, deleting: false});
  };

  deleteCancelHandler = () => {
    this.setState({deleting: false});
  }

  render() { 
    const {term, companies} = this.state;

    return (
      <React.Fragment>
        <Modal 
          show={this.state.deleting} 
          modalClosed={this.deleteCancelHandler} 
        >
          <DeleteCompany 
            delete={this.deleteHandler} 
            deleteCancel={this.deleteCancelHandler}
          />
        </Modal>
        <SearchBox 
          change={this.searchHandler} 
          value={term} 
          placeholder="Search Companies…" 
        />       
        <Companies 
          term={term}
          companies={companies}
          sortByName={() => this.sortBy('name')}
          sortByAddress={() => this.sortBy('city')}
          sortByAdded={() => this.sortBy('id')}
          sortingClass={this.state.sorting}
          toggleSortingClass={this.toggleSortingClass}
          deleteInitiate={this.deleteInitiateHandler}
        />             
      </React.Fragment>
    );
  }
};
export default CompaniesContainer;

最后,将一个DeleteCompany组件安装到Modal组件中,其中包含取消和删除按钮:

const deleteCompany = (props) => {
  return (
    <React.Fragment>
      <h3 className={classes.ModalTitle}>Confirm deletion</h3>
      <p className={classes.ModalText}>Are you sure you want to delete the company of <strong>{props.name}</strong></p>
      <ul className={classes.ModalButtonsList}>
        <li className={classes.ModalButtonsListItem}>
          <Button btnType='primary' onClick={props.deleteCancel}>Cancel</Button>
        </li>
        <li className={classes.ModalButtonsListItem}>
          <Button btnType='danger' onClick={props.delete}>Delete</Button>
        </li>
      </ul>
    </React.Fragment>
  );
};

我的问题是,当我单击特定公司行的删除按钮并通过单击模式内的删除按钮确认删除该行时,将删除错误的行。由于某种原因,无论我要删除哪一行,它总是删除表的第一行。有人可以帮我弄清楚为什么会这样吗?

1 个答案:

答案 0 :(得分:2)

因为在DeleteCompany组件中,您没有在delete方法(在CompaniesContainer中定义为deleteHandler)中传递任何索引,

<Button btnType='danger' onClick={props.delete}>Delete</Button>

因此,您似乎正在执行类似[1,2,3].splice(undefined, 1)的操作,它将始终删除第一个元素。

示例

var a = [1,2,3,4];

a.splice(undefined, 1);

console.log('a', a);

解决方案是,单击删除按钮后,您正在将公司名称从CompaniesContainer组件传递到companyTable,因此请使用该名称删除公司而不是索引。

赞:

deleteHandler = (companyIndex) => {
  this.setState(prevState => ({
    companies: prevState.companies.filter(el => el.name != prevState.deletingCompanyName)
  }))
};

注意:如果公司名称不是唯一的,请在此处传递任何唯一值而不是companiesTable中的名称:

<Button btnType={props.btnClass1} onClick={() => props.deleteInitiate(item.id)}>{props.btnText1}</Button>

并使用该ID删除公司。