我的搜索栏 React 没有 return 任何结果
My search bar React does not return any results
我在我的 React-Firebase 中添加了一个搜索栏 Dashboard.As 结果,当我在搜索栏它 returns 是一个空的 table 即使该词存在于 table.
PS:两个结果都显示在下面的截图中
The table initially rendered
table after writing anything in the search bar
Customer.js
import React, { Fragment, useState } from "react";
import { Avatar } from '@material-ui/core';
import PageTitle from "../../../../layouts/PageTitle";
import { Dropdown, Table } from "react-bootstrap";
import { fire } from "../../../../../fire";
import { firestore } from "../../../../../fire";
import { collection, query, where } from "../../../../../fire";
import App from "../../../../../App";
export default class Recipe extends React.Component {
state = {
searchTerm : "",
Users: []
}
constructor(props){
super(props);
}
searchByTerm = (value) => {
this.setState({searchTerm : value});
}
componentDidMount() {
firestore.collection("Users").get().then((querySnapshot) => {
let User = []
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data().lastn}`);
User.push({
id : doc.id,
data: doc.data()})
});
this.setState({Users : User})
});
}
delete = (id) => {
console.log(id)
firestore.collection("Users").doc(id).delete().then(() => {
console.log("Document successfully deleted!");
this.props.history.push("#")
}).catch((error) => {console.error("Error removing document: ",
error);
});
}
render() {
return (
<Fragment>
<div className="col-12">
<div className="card">
<div className="card-header">
<div className="input-group search-area d-lg-inline-flex d-none mr-
5">
<input
type="text"
className="form-control"
placeholder="Search here"
onChange ={(e) => {
this.searchByTerm(e.target.value);
}}
/>
<div className="input-group-append">
<span className="input-group-text"
>
<svg
width={20}
height={20}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M23.7871 22.7761L17.9548 16.9437C19.5193 15.145 20.4665 12.7982 20.4665 10.2333C20.4665 4.58714 15.8741 0 10.2333 0C4.58714 0 0 4.59246 0 10.2333C0 15.8741 4.59246 20.4665 10.2333 20.4665C12.7982 20.4665 15.145 19.5193 16.9437 17.9548L22.7761 23.7871C22.9144 23.9255 23.1007 24 23.2816 24C23.4625 24 23.6488 23.9308 23.7871 23.7871C24.0639 23.5104 24.0639 23.0528 23.7871 22.7761ZM1.43149 10.2333C1.43149 5.38004 5.38004 1.43681 10.2279 1.43681C15.0812 1.43681 19.0244 5.38537 19.0244 10.2333C19.0244 15.0812 15.0812 19.035 10.2279 19.035C5.38004 19.035 1.43149 15.0865 1.43149 10.2333Z"
fill="#A4A4A4"
/>
</svg>
</span>
</div> </div>
<h4 className="card-title">Customer List </h4>
</div>
<div className="card-body">
<Table responsive className="w-100">
<div id="example_wrapper" className="dataTables_wrapper">
<table id="example" className="display w-100 dataTable">
<thead>
<tr role="row">
<th>Avatar</th>
<th>Email</th>
<th>Firstname</th>
<th>Lastname</th>
<th>PhoneNumber</th>
{/* <th className="pl-5 width200">
Billing Address
</th> */}
<th>Action</th>
</tr>
</thead>
<tbody>
{this.state.Users.filter( (val) =>{
const { email = "", firstname = "" } = val;
// console.log(this.state.searchTerm);
if (this.state.searchTerm === "") {
return val;
} else if (
email.toLowerCase().includes(this.state.searchTerm.toLowerCase()) ||
firstname.toLowerCase().includes(this.state.searchTerm.toLowerCase())
) {
return val;
}
}).map(data => {
return (
<tr>
<td> <Avatar className ="rounded-circle img-fluid" src={data.data.avatar}/> </td>
<td>{data.data.email}</td>
<td>{data.data.firstname}</td>
<td>{data.data.datalastname}</td>
<td>{data.data.phonenumber}</td>
<td>
<div
className="btn btn-danger shadow btn-xs sharp" onClick ={this.delete.bind(this, data.id)}
>
<i className="fa fa-trash"></i> </div></td>
</tr>
);
})}
</tbody>
</table>
</div>
</Table>
</div>
</div>
</div>
</Fragment>
);
};
};
Array.prototype.filter
回调应该是 return 布尔值,而不是被迭代的元素。
这就是我建议重写过滤器函数的方式:如果没有搜索词(即 falsey),则 return true 表示迭代的所有元素应该 return,否则 return比较的结果。
const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();
...
Users.filter((val) => {
const { data: { email = "", firstname = "" } = {} } = val;
if (term) {
return (
email.toLowerCase().includes(term) ||
firstname.toLowerCase().includes(term)
);
}
return true;
})
稍微简洁一点的版本可以这样写:
const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();
...
Users.filter(({ data: { email = "", firstname = "" } = {} }) =>
term ? email.concat(firstname).toLowerCase().includes(term) : true
)
更新
在你说你实施了我的建议但它仍然不起作用之后我仔细查看了你正在渲染的内容并注意到在 .map
回调中你引用了每个字段(email
, firstname
, 等等...) 来自每个元素上的 data
属性。由于您似乎能够在未应用过滤器时呈现数据,因此我假设此结构是正确的。因此,.filter
回调需要 也 从 data
属性 引用嵌套字段属性].我已经更新了上面的代码片段。
我在我的 React-Firebase 中添加了一个搜索栏 Dashboard.As 结果,当我在搜索栏它 returns 是一个空的 table 即使该词存在于 table.
PS:两个结果都显示在下面的截图中
The table initially rendered
table after writing anything in the search bar
Customer.js
import React, { Fragment, useState } from "react";
import { Avatar } from '@material-ui/core';
import PageTitle from "../../../../layouts/PageTitle";
import { Dropdown, Table } from "react-bootstrap";
import { fire } from "../../../../../fire";
import { firestore } from "../../../../../fire";
import { collection, query, where } from "../../../../../fire";
import App from "../../../../../App";
export default class Recipe extends React.Component {
state = {
searchTerm : "",
Users: []
}
constructor(props){
super(props);
}
searchByTerm = (value) => {
this.setState({searchTerm : value});
}
componentDidMount() {
firestore.collection("Users").get().then((querySnapshot) => {
let User = []
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data().lastn}`);
User.push({
id : doc.id,
data: doc.data()})
});
this.setState({Users : User})
});
}
delete = (id) => {
console.log(id)
firestore.collection("Users").doc(id).delete().then(() => {
console.log("Document successfully deleted!");
this.props.history.push("#")
}).catch((error) => {console.error("Error removing document: ",
error);
});
}
render() {
return (
<Fragment>
<div className="col-12">
<div className="card">
<div className="card-header">
<div className="input-group search-area d-lg-inline-flex d-none mr-
5">
<input
type="text"
className="form-control"
placeholder="Search here"
onChange ={(e) => {
this.searchByTerm(e.target.value);
}}
/>
<div className="input-group-append">
<span className="input-group-text"
>
<svg
width={20}
height={20}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M23.7871 22.7761L17.9548 16.9437C19.5193 15.145 20.4665 12.7982 20.4665 10.2333C20.4665 4.58714 15.8741 0 10.2333 0C4.58714 0 0 4.59246 0 10.2333C0 15.8741 4.59246 20.4665 10.2333 20.4665C12.7982 20.4665 15.145 19.5193 16.9437 17.9548L22.7761 23.7871C22.9144 23.9255 23.1007 24 23.2816 24C23.4625 24 23.6488 23.9308 23.7871 23.7871C24.0639 23.5104 24.0639 23.0528 23.7871 22.7761ZM1.43149 10.2333C1.43149 5.38004 5.38004 1.43681 10.2279 1.43681C15.0812 1.43681 19.0244 5.38537 19.0244 10.2333C19.0244 15.0812 15.0812 19.035 10.2279 19.035C5.38004 19.035 1.43149 15.0865 1.43149 10.2333Z"
fill="#A4A4A4"
/>
</svg>
</span>
</div> </div>
<h4 className="card-title">Customer List </h4>
</div>
<div className="card-body">
<Table responsive className="w-100">
<div id="example_wrapper" className="dataTables_wrapper">
<table id="example" className="display w-100 dataTable">
<thead>
<tr role="row">
<th>Avatar</th>
<th>Email</th>
<th>Firstname</th>
<th>Lastname</th>
<th>PhoneNumber</th>
{/* <th className="pl-5 width200">
Billing Address
</th> */}
<th>Action</th>
</tr>
</thead>
<tbody>
{this.state.Users.filter( (val) =>{
const { email = "", firstname = "" } = val;
// console.log(this.state.searchTerm);
if (this.state.searchTerm === "") {
return val;
} else if (
email.toLowerCase().includes(this.state.searchTerm.toLowerCase()) ||
firstname.toLowerCase().includes(this.state.searchTerm.toLowerCase())
) {
return val;
}
}).map(data => {
return (
<tr>
<td> <Avatar className ="rounded-circle img-fluid" src={data.data.avatar}/> </td>
<td>{data.data.email}</td>
<td>{data.data.firstname}</td>
<td>{data.data.datalastname}</td>
<td>{data.data.phonenumber}</td>
<td>
<div
className="btn btn-danger shadow btn-xs sharp" onClick ={this.delete.bind(this, data.id)}
>
<i className="fa fa-trash"></i> </div></td>
</tr>
);
})}
</tbody>
</table>
</div>
</Table>
</div>
</div>
</div>
</Fragment>
);
};
};
Array.prototype.filter
回调应该是 return 布尔值,而不是被迭代的元素。
这就是我建议重写过滤器函数的方式:如果没有搜索词(即 falsey),则 return true 表示迭代的所有元素应该 return,否则 return比较的结果。
const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();
...
Users.filter((val) => {
const { data: { email = "", firstname = "" } = {} } = val;
if (term) {
return (
email.toLowerCase().includes(term) ||
firstname.toLowerCase().includes(term)
);
}
return true;
})
稍微简洁一点的版本可以这样写:
const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();
...
Users.filter(({ data: { email = "", firstname = "" } = {} }) =>
term ? email.concat(firstname).toLowerCase().includes(term) : true
)
更新
在你说你实施了我的建议但它仍然不起作用之后我仔细查看了你正在渲染的内容并注意到在 .map
回调中你引用了每个字段(email
, firstname
, 等等...) 来自每个元素上的 data
属性。由于您似乎能够在未应用过滤器时呈现数据,因此我假设此结构是正确的。因此,.filter
回调需要 也 从 data
属性 引用嵌套字段属性].我已经更新了上面的代码片段。