我有一个围绕React Table组件构建的功能组件,它使用Apollo GraphQL client进行服务器端分页和搜索.我试图为搜索实现go Bouncing,以便在用户停止输入该值后,只对服务器执行一个查询.我try 过lodash debounceawesome debounce promise解决方案,但仍然会对服务器执行一个查询,查询搜索字段中键入的每个字符.

以下是我的组件(编辑了不相关的信息):

import React, {useEffect, useState} from 'react';
import ReactTable from "react-table";
import _ from 'lodash';
import classnames from 'classnames';
import "react-table/react-table.css";
import PaginationComponent from "./PaginationComponent";
import LoadingComponent from "./LoadingComponent";
import {Button, Icon} from "../../elements";
import PropTypes from 'prop-types';
import Card from "../card/Card";
import './data-table.css';

import debounce from 'lodash/debounce';

function DataTable(props) {
    const [searchText, setSearchText] = useState('');
     const [showSearchBar, setShowSearchBar] = useState(false);

    const handleFilterChange = (e) => {
        let searchText = e.target.value;
        setSearchText(searchText);
        if (searchText) {
            debounceLoadData({
                columns: searchableColumns,
                value: searchText
            });
        }
    };

    const loadData = (filter) => {
        // grab one extra record to see if we need a 'next' button
        const limit = pageSize + 1;
        const offset = pageSize * page;

        if (props.loadData) {
            props.loadData({
                variables: {
                    hideLoader: true,
                    opts: {
                        offset,
                        limit,
                        orderBy,
                        filter,
                        includeCnt: props.totalCnt > 0
                    }
                },
                updateQuery: (prev, {fetchMoreResult}) => {
                    if (!fetchMoreResult) return prev;
                    return Object.assign({}, prev, {
                        [props.propName]: [...fetchMoreResult[props.propName]]
                    });
                }
            }).catch(function (error) {
                console.error(error);
            })
        }
    };

    const debounceLoadData = debounce((filter) => {
        loadData(filter);
    }, 1000);

    return (
        <div>
            <Card style={{
                border: props.noCardBorder ? 'none' : ''
            }}>
                {showSearchBar ? (
                        <span className="card-header-icon"><Icon className='magnify'/></span>
                        <input
                            autoFocus={true}
                            type="text"
                            className="form-control"
                            onChange={handleFilterChange}
                            value={searchText}
                        />
                        <a href="javascript:void(0)"><Icon className='close' clickable
                                                           onClick={() => {
                                                               setShowSearchBar(false);
                                                               setSearchText('');
                                                           }}/></a>
                ) : (
                        <div>
                           {visibleData.length > 0 && (
                                <li className="icon-action"><a 
href="javascript:void(0)"><Icon className='magnify' onClick= {() => {
    setShowSearchBar(true);
    setSearchText('');
}}/></a>
                                </li>
                            )}
                        </div>
                    )
                )}
                <Card.Body className='flush'>
                    <ReactTable
                        columns={columns}
                        data={visibleData}
                    />
                </Card.Body>
            </Card>
        </div>
    );
}

export default DataTable

... 这就是结果:link

推荐答案

debounceLoadData将是每个渲染的新功能.您可以使用useCallback钩子来确保相同的函数在渲染之间被持久化,并且它将按预期工作.

useCallback(debounce(loadData, 1000), []);

const { useState, useCallback } = React;
const { debounce } = _;

function App() {
  const [filter, setFilter] = useState("");
  const debounceLoadData = useCallback(debounce(console.log, 1000), []);

  function handleFilterChange(event) {
    const { value } = event.target;

    setFilter(value);
    debounceLoadData(value);
  }

  return <input value={filter} onChange={handleFilterChange} />;
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

Reactjs相关问答推荐

当我在React中使用类方法更新模型的状态时,它在严格模式下触发两次

导致类型错误的调度不是函数";

如何在整个应用程序中显示通用弹出窗口中的点击事件

FireBase Reaction Native-在呈现视图之前等待响应

在Reaction中导入';图片&文件夹时出错

用于获取带有事件处理程序的API的动态路由

如何使用.Aggregate从多个集合中获取数据,包括使用Mongoose+NextJS的SUM值

滚动视图样式高度没有任何区别

Next.js `getLayout` 函数没有被调用

Symfony ux-react:使用react_component()时React组件不会渲染

从 redux 调用UPDATE_DATA操作时状态变得未定义

React中的功能性组件克隆优化

try 从 React JS 构建此教程游戏但无法继续前进

从 React 应用程序调用未经身份验证的 graphql 查询时出现错误:没有当前用户

为什么 createSlice 中的 reducer 不能以不同的方式改变状态?

在 React 中,为什么在使用 addEventListener 时外部元素上的 onclick 事件监听器在内部元素的 onclick 事件监听器之前执行?

位于组件material-ui中的TextField中的 map 功能不起作用

如何在 JSX 中使用 -webkit- 前缀?

当父组件重新渲染时做出react ,我失go 了子状态.我错过了什么?

链接的音译 Gatsby JS