如何在这个 React 组件中去除搜索功能?
How to debounce search function in this React Component?
我有一个组件获取员工列表作为道具。我还创建了一个输入元素,用于按字符串过滤列表。
我将过滤逻辑移动到需要数据列表和搜索值的函数中,因此它可以 return 过滤列表。
我想在搜索输入中添加 lodash debounce,这样每当用户输入内容时,它都会等待 1 秒并过滤掉列表。
import React from 'react';
import _ from "lodash"
import { IEmployee } from '../../../store/EmployeesStore/reducer'
import AddEmployee from '../AddEmployee/AddEmployee';
import EmployeeItem from './EmployeeItem/EmployeeItem';
import { TextField } from '@material-ui/core';
import InputAdornment from '@material-ui/core/InputAdornment';
import SearchIcon from '@material-ui/icons/Search';
export interface EmployeeProps {
employees: IEmployee[];
}
class EmployeeList extends React.Component<EmployeeProps> {
state = {
searchValue: ''
};
//function which returns filtered list
filterList = (employeesList: IEmployee[], searchValue: string) => {
return employeesList.filter((item: any) => {
const fullName = `${item.firstName}${item.lastName}`.toLowerCase();
const reversedFullName = `${item.lastName}${item.firstName}`.toLowerCase();
const trimmedSearchValue = searchValue
.replace(/\s+/g, '')
.toLowerCase();
return (
fullName.includes(trimmedSearchValue) ||
reversedFullName.includes(trimmedSearchValue)
);
});
};
render() {
// saving filtered list data in filteredList variable
let filteredList = this.filterList(this.props.employees, this.state.searchValue)
return (
<>
<AddEmployee />
<TextField
style={{ marginLeft: '20px' }}
size="medium"
id="input-with-icon-textfield"
variant="outlined"
value={this.state.searchValue}
onChange={(e) => this.setState({ searchValue: e.target.value })}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<SearchIcon />
</InputAdornment>
),
}}
InputLabelProps={{
shrink: true,
}}
/>
<div>
<ul
style={{
margin: '0px',
padding: '0px',
listStyle: 'none',
display: 'flex',
flexWrap: 'wrap',
}}
>
{filteredList.map((employee) => {
return <EmployeeItem key={employee.id} {...employee} />;
})}
</ul>
</div>
</>
);
}
}
export default EmployeeList;
我应该在哪里添加 _.debounce 函数以及如何添加?
您不应在 return 语句中调用 filterList 函数,而必须在 TextField 的 onChange 上调用它。
像这样:
handleChange = (e) => {
this.setState({ searchValue: e.target.value })};
const debouncedCall = _.debounce(() => this.filterList(this.props.employees, e.target.value), 1000);
debouncedCall();
}
//Rest of your code
render() {
<TextField
onChange={(e) => handleChange(e)}
...other attributes
/>
}
仅显示相关更改:-
constructor (props) {
super(props)
this.state = {
searchValue: ''
};
this.debouncedHandler = _.debounce(this.handleChange.bind(this),1000);
}
handleChange = (e) => {
this.setState({ searchValue: e.target.value })};
}
<TextField
style={{ marginLeft: '20px' }}
size="medium"
id="input-with-icon-textfield"
variant="outlined"
value={this.state.searchValue}
onChange={this.debouncedHandler}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<SearchIcon />
</InputAdornment>
),
}}
InputLabelProps={{
shrink: true,
}}
/>
解释:我们通过onChange
重复调用debouncedHandler
所以我们需要确保handleChange
只在爆发时被触发1000
毫秒结束,在此期间没有调用 debouncedHandler
。如果在该突发间隔内再次调用 debouncedHandler
,则新的突发间隔开始。
从您的组件的角度来看,我们每次都将 handleChange
内的主要逻辑的执行延迟 1000
毫秒,除非用户没有在 [=21] 中输入任何其他字符=] 1000ms
中的组件,一旦 1000
毫秒结束,setState
将被触发以声明状态 ---> 意味着重新渲染 ----->意味着新的 filteredList 并显示给用户。
我有一个组件获取员工列表作为道具。我还创建了一个输入元素,用于按字符串过滤列表。 我将过滤逻辑移动到需要数据列表和搜索值的函数中,因此它可以 return 过滤列表。
我想在搜索输入中添加 lodash debounce,这样每当用户输入内容时,它都会等待 1 秒并过滤掉列表。
import React from 'react';
import _ from "lodash"
import { IEmployee } from '../../../store/EmployeesStore/reducer'
import AddEmployee from '../AddEmployee/AddEmployee';
import EmployeeItem from './EmployeeItem/EmployeeItem';
import { TextField } from '@material-ui/core';
import InputAdornment from '@material-ui/core/InputAdornment';
import SearchIcon from '@material-ui/icons/Search';
export interface EmployeeProps {
employees: IEmployee[];
}
class EmployeeList extends React.Component<EmployeeProps> {
state = {
searchValue: ''
};
//function which returns filtered list
filterList = (employeesList: IEmployee[], searchValue: string) => {
return employeesList.filter((item: any) => {
const fullName = `${item.firstName}${item.lastName}`.toLowerCase();
const reversedFullName = `${item.lastName}${item.firstName}`.toLowerCase();
const trimmedSearchValue = searchValue
.replace(/\s+/g, '')
.toLowerCase();
return (
fullName.includes(trimmedSearchValue) ||
reversedFullName.includes(trimmedSearchValue)
);
});
};
render() {
// saving filtered list data in filteredList variable
let filteredList = this.filterList(this.props.employees, this.state.searchValue)
return (
<>
<AddEmployee />
<TextField
style={{ marginLeft: '20px' }}
size="medium"
id="input-with-icon-textfield"
variant="outlined"
value={this.state.searchValue}
onChange={(e) => this.setState({ searchValue: e.target.value })}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<SearchIcon />
</InputAdornment>
),
}}
InputLabelProps={{
shrink: true,
}}
/>
<div>
<ul
style={{
margin: '0px',
padding: '0px',
listStyle: 'none',
display: 'flex',
flexWrap: 'wrap',
}}
>
{filteredList.map((employee) => {
return <EmployeeItem key={employee.id} {...employee} />;
})}
</ul>
</div>
</>
);
}
}
export default EmployeeList;
我应该在哪里添加 _.debounce 函数以及如何添加?
您不应在 return 语句中调用 filterList 函数,而必须在 TextField 的 onChange 上调用它。
像这样:
handleChange = (e) => {
this.setState({ searchValue: e.target.value })};
const debouncedCall = _.debounce(() => this.filterList(this.props.employees, e.target.value), 1000);
debouncedCall();
}
//Rest of your code
render() {
<TextField
onChange={(e) => handleChange(e)}
...other attributes
/>
}
仅显示相关更改:-
constructor (props) {
super(props)
this.state = {
searchValue: ''
};
this.debouncedHandler = _.debounce(this.handleChange.bind(this),1000);
}
handleChange = (e) => {
this.setState({ searchValue: e.target.value })};
}
<TextField
style={{ marginLeft: '20px' }}
size="medium"
id="input-with-icon-textfield"
variant="outlined"
value={this.state.searchValue}
onChange={this.debouncedHandler}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<SearchIcon />
</InputAdornment>
),
}}
InputLabelProps={{
shrink: true,
}}
/>
解释:我们通过onChange
重复调用debouncedHandler
所以我们需要确保handleChange
只在爆发时被触发1000
毫秒结束,在此期间没有调用 debouncedHandler
。如果在该突发间隔内再次调用 debouncedHandler
,则新的突发间隔开始。
从您的组件的角度来看,我们每次都将 handleChange
内的主要逻辑的执行延迟 1000
毫秒,除非用户没有在 [=21] 中输入任何其他字符=] 1000ms
中的组件,一旦 1000
毫秒结束,setState
将被触发以声明状态 ---> 意味着重新渲染 ----->意味着新的 filteredList 并显示给用户。