javascript - 如何用React对同一张表数据进行过滤和排序?

标签 javascript reactjs sorting filter state

我遇到一个问题,加载页面后,我可以按“姓名”列(升序或降序)对表格进行排序 - - 或 - - 使用搜索栏过滤员工姓名。我的问题是,一旦我按字母顺序排序,搜索/过滤器就不再起作用。

我对 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 中的值。

<小时/>

please let me know if there's something obvious I'm doing wrong

您正在为自己制造麻烦,因为您正在过滤/排序相同的数据集合。这就是为什么您需要在渲染中执行该操作,因为您正在尝试维护原始列表以供以后使用。

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

  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

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

关于javascript - 如何用React对同一张表数据进行过滤和排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61284113/

相关文章:

javascript - 在 Meteor 中使用 Chart.js 时出现 'Chart is not defined' 错误

javascript - Material-UI AppBar 按钮在较小的屏幕上相互折叠

reactjs - 是否可以使 VictoryPie 切片相互重叠?

javascript - React <select> 自动改变不触发onChange

c# - 对目录文件进行排序并获取最高的文件名

javascript - Highcharts 对堆积条形图进行排序

javascript - 无法在 'removeChild' 滑出错误上执行 'Node'

javascript - 克隆 div 和在循环中创建的 div 之间有什么区别吗?

javascript - AJAX 事件有效,但不会在不刷新的情况下同时反射(reflect) PHP MYSQL 结果。

c++ - 在比较函数中使用非静态类成员