用过滤器反应JS表

时间:2019-02-07 00:12:33

标签: javascript reactjs

我正在尝试修改react js文档here中的此表 并遇到了一些奇怪的问题,如下面的屏幕截图所示。 enter image description here

我们尝试过滤lBir

enter image description here

最终结果是我得到了额外的行。这是所有代码的全部内容。

import React from 'react';
import ReactDOM from 'react-dom';
  
  class UserRow extends React.Component {
    render() {
      const user = this.props.user;
      const name = user.name;
  
      return (
        <tr>
          <td>{name}</td>
          <td>{user.system}</td>
        </tr>
      );
    }
  }
  
  class UserTable extends React.Component {
    render() {
      const filterText = this.props.filterText;  
      const rows = [];  
      this.props.users.forEach((user) => {
        console.log(this.props.users);
        if (user.name.indexOf(filterText) === -1) {
        //   console.log('filter text = -1')
          return;
        }
        rows.push(
          <UserRow
            user={user}
            key={user.name}
          />
        );
      });
  
      return (
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>system</th>
            </tr>
          </thead>
          <tbody>{rows}</tbody>
        </table>
      );
    }
  }
  
  class SearchBar extends React.Component {
    constructor(props) {
      super(props);
      this.handleFilterTextChange = this.handleFilterTextChange.bind(this);
    }
    
    handleFilterTextChange(e) {
      this.props.onFilterTextChange(e.target.value);
    }
    
    render() {
      return (
        <form>
          <input
            type="text"
            placeholder="Search..."
            value={this.props.filterText}
            onChange={this.handleFilterTextChange}
          />
        </form>
      );
    }
  }
  
  class FilterableUserTable extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        filterText: ''      
    };
      
      this.handleFilterTextChange = this.handleFilterTextChange.bind(this);
    }
  
    handleFilterTextChange(filterText) {
        console.log(filterText);
      this.setState({
        filterText: filterText
      });
    }
    
    render() {
      return (
        <div>
          <SearchBar
            filterText={this.state.filterText}
            onFilterTextChange={this.handleFilterTextChange}
          />
          <UserTable
            users={this.props.users}
            filterText={this.state.filterText}
          />
        </div>
      );
    }
  }
  
  
  const USERS = [
    {name: 'lJames', system: 'test@testy.com'},
    {name: 'lJames', system: 'test@tester.com'},
    {name: 'lBird', system: 'lbird@moretesting.com'},
    {name: 'mJordan', system: 'lbird@somemore.com'},
    {name: 'tester', system: 'mjordan@nba.com'},
  ];
  
  ReactDOM.render(
    <FilterableUserTable users={USERS} />,
    document.getElementById('container')
  );
  
  
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="container"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

我可以在控制台中看到以下警告: “警告:遇到两个具有相同密钥lJames的子代。密钥应该是唯一的,以便组件在更新过程中保持其身份。非唯一密钥可能会导致子代被复制和/或省略-这种行为不受支持,并且可能会在将来的版本中更改。”

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

React使用键作为标识列表中组件的一种方式,它们在该列表(React docs)中应该是唯一的。如果有多个具有相同键的组件,则可能会导致出现与您看到的组件类似的问题(因为您使用name作为键,并且两个用户的名称为lJames)。

您可以通过为每个用户提供唯一的id属性来解决此问题,或者使用串联的用户和电子邮件作为密钥-key={user.name + user.system}

答案 1 :(得分:0)

使用React在任何表上应用过滤器

例如:- 1.首先,您需要状态来存储所有数据

state = {
  List: [],
  backupList: []
};
All data should be stored in List[]. And backupList[] is needed for reference
which acts as temporary variable.

2。制作一个 text 类型的输入框,并使用 onChange 事件。

<input type="text" placeholder="Filter" onChange={this.filterList} />

3。制作一个名为 filterList

的方法
filterList = (event) => {
var updatedList = this.state.backupList;
updatedList = updatedList.filter(function(list) {
  return (
    list.fullname.toLowerCase().search(event.target.value.toLowerCase()) !==
    -1
  );
});
this.setState({
  List: updatedList
});
};

在这里,我正在根据全名过滤表,但是您可以对不同的数据使用此方法。