如何使用React过滤和排序相同的表数据?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用React过滤和排序相同的表数据?相关的知识,希望对你有一定的参考价值。

我遇到了一个问题,在该页面上,我可以按“名称”列(升序或降序)对表格进行排序--或--使用搜索栏来筛选雇员的姓名。我的问题是,按字母顺序排序后,搜索/过滤器将不再起作用。

我对React还是很陌生(我的代码很确定),所以如果有什么明显的地方我做错了,请告诉我。预先感谢!

import React,  Component  from "react";
import API from "../utils/API"
import EmployeeRow from "./EmployeeRow"

class TableMain extends Component 
    state = 
        result: [],
        search: "",
        sortOrder: "descending"
    

    componentDidMount() 
        API.search()
            .then(results => 
                console.log(results)
                this.setState(
                    result: results.data.results.map((res, i) => (
                        image: res.picture.large,
                        firstName: res.name.first,
                        lastName: res.name.last,
                        phone: res.phone,
                        email: res.email,
                        dob: res.dob.date,
                        key: i
                    )
                    )
                )
            )
    ;

    filterResults = (results) => 
        const value = this.state.search
        const finalResult = results.filter((employee) => 
            const lastName = employee.lastName.toLowerCase();
            const firstName = employee.firstName.toLowerCase()
            const fullName = firstName + " " + lastName

            if (fullName.includes(value)) 
                return employee
            
        );

        return finalResult
    ;

    sortResults = (event) => 
        const results = this.state.result
        // const id = event.target.id
        // if (id === 'name')
        //  else if (id === 'phone')
        //  else if (id === 'email')
        // 
        if (this.state.sortOrder === "descending") 
            results.sort((a, b) => 
                if (a.firstName > b.firstName) 
                    return -1
                
                return a.firstName > b.firstName ? 1 : 0
            , 
            this.setState( sortOrder: "ascending" ))
         else if (this.state.sortOrder === "ascending") 
            results.sort((a, b) => 
                if (a.firstName < b.firstName) 
                    return -1
                
                return a.firstName > b.firstName ? 1 : 0
            , 
            this.setState( sortOrder: "descending" ))
        

        console.log("RESULTS: ", results)

        this.setState(
            sortedResults: results,
            isSorted: true
        )
    

    onChange = e => 
        const value = e.target.value;
        if (!value) 
            this.setState( isSearchEmpty: true );
         else 
            this.setState( search: e.target.value, isSearchEmpty: false );
        
    

    render() 
        // console.log("State", this.state)
        let employeeResults = this.state.result 

        if (this.state.isSearchEmpty) 
            employeeResults = this.state.result
         else 
            employeeResults = this.filterResults(this.state.result)
        

        if (this.state.isSorted) 
            employeeResults = this.state.sortedResults
        

        return (
            <div>
                <input label="Search" onChange=this.onChange />
                <div className="row">
                    <table style= width: "100%" >
                        <tbody>
                            <tr>
                                <th>Image</th>
                                <th style= cursor: "pointer"  onClick=this.sortResults id="name">Name</th>
                                <th id="phone">Phone</th>
                                <th id="email">Email</th>
                                <th id="dob">DOB</th>
                            </tr>
                            [...employeeResults].map((item) =>
                                <EmployeeRow
                                    image=item.image
                                    firstName=item.firstName
                                    lastName=item.lastName
                                    email=item.email
                                    phone=item.phone
                                    dob=item.dob
                                    key=item.key
                                />
                            )
                        </tbody>
                    </table>
                </div>
            </div>
        )



export default TableMain;
答案

问题是:

    if (this.state.isSorted) 
      employeeResults = this.state.sortedResults;
    

排序时,将state.isSorted设置为true,但是一旦完成,就永远不会将其设置为false。然后尝试进行过滤时,请执行过滤器:

    if (this.state.isSearchEmpty) 
      employeeResults = this.state.result;
     else 
      employeeResults = this.filterResults(this.state.result);
    

    if (this.state.isSorted)  // this is never reset after sorting.
      employeeResults = this.state.sortedResults;
    

但是由于this.state.isSorted仍然为true,因此请再次使用this.state.sortedResults中的值。


请让我知道我做错了什么明显的事情

您正在过滤自己的数据集/对它们进行排序时,让自己变得棘手。这就是为什么您需要在渲染中执行操作的原因,因为您试图维护原始列表以供以后使用。

如果将列表分为两个集合:原始未修改列表和显示列表,则始终可以引用原始列表来执行过滤/排序。

  componentDidMount() 
    API.search().then(results => 
      const tableData = results.data.results.map((res, i) => (
        image: res.picture.large,
        firstName: res.name.first,
        lastName: res.name.last,
        phone: res.phone,
        email: res.email,
        dob: res.dob.date,
        key: i
      ));

      this.setState( originalResults: tableData, displayResults: tableData );
    );
  

然后在onChange出现时就可以进行过滤:

  onChange = e => 
    const query = e.target.value;

    this.setState(prevState => (
      displayResults:
        query.length > 0
          ? this.filterResults(query, prevState.originalResults)
          : prevState.originalResults
    ));
  ;

并且类似地,可以对显示结果而不是整个结果进行排序,这意味着您现在可以对过滤后的结果进行排序。

我在这里创建了一个示例https://codesandbox.io/s/sad-cannon-d61z6

我删除了所有缺少的功能。

以上是关于如何使用React过滤和排序相同的表数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在vue js中集成类似Excel的表排序和过滤

如何在同一页面中使用相同的javascript过滤器两次使用不同的表?

SQL:只选择一行具有相同值的表

设置带有过滤器和排序的 HTML 表格

如何在 React 中创建可排序的表?如何从排序的对象访问类方法?

使用具有不同片段字段的相同中继根查询的多个 react-router-relay 路由