Converting class component to functional component TypeError: users.filter is not a function

Converting class component to functional component TypeError: users.filter is not a function

制作员工目录,我正在尝试将 class 组件转换为功能组件。导航、搜索和 table 将呈现,但对 api 的调用不起作用。得到一个 TypeError: users.filter is not a function 这是工作的 class 组件和进行中的功能组件。我不知道有什么不同。

import React, { Component } from "react";
import DataTable from "./DataTable";
import Nav from "./Nav";
import API from "../utils/API";
import "../styles/DataArea.css";

export default class DataArea extends Component {
  state = {
    users: [{}],
    order: "descend",
    filteredUsers: [{}]
  }

  headings = [
    { name: "Image", width: "10%" },
    { name: "Name", width: "10%" },
    { name: "Phone", width: "20%" },
    { name: "Email", width: "20%" },
    { name: "DOB", width: "10%" }
  ]

  handleSort = heading => {
    if (this.state.order === "descend") {
      this.setState({
        order: "ascend"
      })
    } else {
      this.setState({
        order: "descend"
      })
    }

    const compareFnc = (a, b) => {
      if (this.state.order === "ascend") {
        // account for missing values
        if (a[heading] === undefined) {
          return 1;
        } else if (b[heading] === undefined) {
          return -1;
        }
        // numerically
        else if (heading === "name") {
          return a[heading].first.localeCompare(b[heading].first);
        } else {
          return a[heading] - b[heading];
        }
      } else {
        // account for missing values
        if (a[heading] === undefined) {
          return 1;
        } else if (b[heading] === undefined) {
          return -1;
        }
        // numerically
        else if (heading === "name") {
          return b[heading].first.localeCompare(a[heading].first);
        } else {
          return b[heading] - a[heading];
        }
      }

    }
    const sortedUsers = this.state.filteredUsers.sort(compareFnc);
    this.setState({ filteredUsers: sortedUsers });
  }

  handleSearchChange = event => {
    console.log(event.target.value);
    const filter = event.target.value;
    const filteredList = this.state.users.filter(item => {
      // merge data together, then see if user input is anywhere inside
      let values = Object.values(item)
        .join("")
        .toLowerCase();
      return values.indexOf(filter.toLowerCase()) !== -1;
    });
    this.setState({ filteredUsers: filteredList });
  }

  componentDidMount() {
    API.getUsers().then(results => {
      this.setState({
        users: results.data.results,
        filteredUsers: results.data.results
      });
    });
  }

  render() {
    return (
      <>
        <Nav handleSearchChange={this.handleSearchChange} />
        <div className="data-area">
          <DataTable
            headings={this.headings}
            users={this.state.filteredUsers}
            handleSort={this.handleSort}
          />
        </div>
      </>
    );
  }
}
import React, { useState, useEffect } from "react";
import DataTable from "./DataTable";
import Nav from "./Nav";
import API from "../utils/API";
import "../styles/DataArea.css";

const DataArea = () => {

  const [users, setUsers] = useState([{}]);
  const [order, setOrder] = useState("descend");
  const [filteredUsers, setFilteredUsers] = useState([{}]);


  const headings = [
    { name: "Image", width: "10%" },
    { name: "Name", width: "10%" },
    { name: "Phone", width: "20%" },
    { name: "Email", width: "20%" },
    { name: "DOB", width: "10%" },
  ];

  const handleSort = (heading) => {

    if (order === "descend") {
      setOrder((order = "ascend"));
    } else {
      setOrder((order = "descend"));
    }

    const compareFnc = (a, b) => {
      if (order === "ascend") {
        // account for missing values
        if (a[heading] === undefined) {
          return 1;
        } else if (b[heading] === undefined) {
          return -1;
        }
        // numerically
        else if (heading === "name") {
          return a[heading].first.localeCompare(b[heading].first);
        } else {
          return a[heading] - b[heading];
        }
      } else {
        // account for missing values
        if (a[heading] === undefined) {
          return 1;
        } else if (b[heading] === undefined) {
          return -1;
        }
        // numerically
        else if (heading === "name") {
          return b[heading].first.localeCompare(a[heading].first);
        } else {
          return b[heading] - a[heading];
        }
      }
    };

    const sortedUsers = filteredUsers.sort(compareFnc);
    setFilteredUsers({ filteredUsers: sortedUsers });
  };

  let handleSearchChange = (event) => {
    console.log(event.target.value);
    const filtered = event.target.value;
    const filteredList = users.filter((item) => {
      // merge data together, then see if user input is anywhere inside
      let values = Object.values(item).join("").toLowerCase();
      return values.indexOf(filtered.toLowerCase()) !== -1;
    });
    setFilteredUsers((filteredUsers = filteredList));
  };

  useEffect(() => {
    API.getUsers().then((results) => {
      setUsers({
        users: results.data.results,
        filteredUsers: results.data.results,
      });
    });

  }, []);
  return (
    <>
      <Nav handleSearchChange={handleSearchChange} />
      <div className="data-area">
        <DataTable
          headings={headings}
          users={filteredUsers}
          handleSort={handleSort}
        />
      </div>
    </>
  );
};

export default DataArea;

问题出在你的 useEffect 钩子上,你将 usersfilteredUsers 都塞进了你的 users 状态。

useEffect(() => {
  API.getUsers().then((results) => {
    setUsers({
      users: results.data.results,
      filteredUsers: results.data.results,
    });
  });
}, []);

应该是

useEffect(() => {
  API.getUsers().then((results) => {
    setUsers(results.data.results);
    setFilteredUsers(results.data.results),
  });
}, []);

您想同时填充 users 状态和 filteredUsers 状态。

设置排序顺序的问题,您正在改变 order 状态:

if (order === "descend") {
  setOrder((order = "ascend")); // <-- mutates
} else {
  setOrder((order = "descend")); // <-- mutates
}

您可以简单地在两者之间切换:

setOrder(order => order === 'ascend' ? 'descend' : 'ascend');

另一个问题出现在您的 handleSort 函数的末尾:

const sortedUsers = filteredUsers.sort(compareFnc);
setFilteredUsers({ filteredUsers: sortedUsers });

这将嵌套 filteredUsers 数组,并就地改变数组,它可能应该使用功能状态更新从以前的状态更新,使用 array.slice 进行复制,然后调用排序。

setFilteredUsers(filteredUsers => filteredUsers.slice().sort(compareFnc));