将类组件转换为功能组件 TypeError: users.filter is not a function
Posted
技术标签:
【中文标题】将类组件转换为功能组件 TypeError: users.filter is not a function【英文标题】:Converting class component to functional component TypeError: users.filter is not a function 【发布时间】:2021-09-11 05:31:53 【问题描述】:创建一个员工目录,我正在尝试将类组件转换为功能组件。导航、搜索和表格将呈现,但对 api 的调用不起作用。得到一个
TypeError: users.filter is not a function
这是工作的类组件和正在进行的功能组件。我不知道有什么不同。
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;
【问题讨论】:
我的错。感谢您修复 @DrewReese! 【参考方案1】:问题在于您的useEffect
钩子,您将users
和filteredUsers
都硬塞到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进行复制,然后调用sort。
setFilteredUsers(filteredUsers => filteredUsers.slice().sort(compareFnc));
【讨论】:
这是可行的,但是当页面开始呈现时,我得到一个失败的编译并且这个错误:` 期望一个赋值或函数调用,而是看到一个表达式 no-unused-expressions` 知道了,我用逗号代替了分号。非常感谢朋友! @KevinMillhouse 啊,太棒了!如果此答案已充分解决您的问题/问题,那么我邀请您接受它(***.com/help/someone-answers)。不要忘记为您在 SO 上找到的有用和/或有用的问题、答案和 cmets 投票。干杯,祝你好运。 太棒了!回答采纳!也感谢您添加的反馈!!我从来没有想过使用三元来切换。非常感谢并再次感谢您的帮助! @KevinMillhouse 如果您将order
转换/重命名为orderAscend
并使其成为布尔值,那么切换它会变得更加简单,setOrderAscend(order => !order)
然后只需检查if (orderAscend) .....
。以上是关于将类组件转换为功能组件 TypeError: users.filter is not a function的主要内容,如果未能解决你的问题,请参考以下文章