【问题标题】:How to debounce search function in this React Component?如何在这个 React 组件中去抖动搜索功能?
【发布时间】:2023-03-09 23:20:01
【问题描述】:

我有一个组件,它获取员工列表作为道具。我还创建了一个输入元素,用于按字符串过滤列表。 我将过滤逻辑移到了一个函数中,该函数需要一个数据列表和一个搜索值,因此它可以返回过滤后的列表。

我想在搜索输入中添加 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 函数以及如何添加?

【问题讨论】:

    标签: javascript reactjs debounce


    【解决方案1】:

    仅显示相关更改:-

    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只有在1000ms的爆发结束并且没有调用debouncedHandler 发生在这段时间内。如果在该突发​​间隔内再次调用 debouncedHandler,则会启动新的突发间隔。

    从您的组件的角度来看,我们每次都将handleChange 内部的主逻辑的执行延迟1000ms,除非用户没有在TextField 组件中输入任何其他字符1000ms ,一旦1000ms 结束,setState 将被触发以声明状态 ---> 表示重新渲染 -----> 表示新的过滤列表并将其显示给用户。

    【讨论】:

      【解决方案2】:

      您不应该在 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
         />
      }
      

      【讨论】:

        猜你喜欢
        • 2021-06-30
        • 2017-06-16
        • 1970-01-01
        • 1970-01-01
        • 2021-08-16
        • 1970-01-01
        • 2023-01-25
        • 1970-01-01
        • 2015-03-03
        相关资源
        最近更新 更多