我有一个围绕React Table组件构建的功能组件,该组件使用Apollo GraphQL客户端进行服务器端分页和搜索。我正在尝试为搜索实现反跳操作,以便一旦用户停止使用该值键入内容,就只对服务器执行一个查询。我已经尝试过lodash的反跳和真棒的反跳承诺解决方案,但仍然针对服务器在搜索字段中键入的每个字符执行查询。
这是我的组件(删除了不相关的信息):
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
Run Code Online (Sandbox Code Playgroud)
...这就是结果:链接
Tho*_*lle 32
debounceLoadData
将是每个渲染的新功能。您可以使用该useCallback
挂钩来确保在渲染之间持久保留相同的功能,并且该功能可以按预期工作。
useCallback(debounce(loadData, 1000), []);
Run Code Online (Sandbox Code Playgroud)
useCallback(debounce(loadData, 1000), []);
Run Code Online (Sandbox Code Playgroud)
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"));
Run Code Online (Sandbox Code Playgroud)
Adr*_*ain 11
添加 Tholle 的答案:如果您想充分利用钩子,您可以使用useEffect
钩子来观察过滤器中的变化并debouncedLoadData
在发生这种情况时运行该函数:
const { useState, useCallback, useEffect } = React;
const { debounce } = _;
function App() {
const [filter, setFilter] = useState("");
const debounceLoadData = useCallback(debounce(fetchData, 1000), []);
useEffect(() => {
debounceLoadData(filter);
}, [filter]);
function fetchData(filter) {
console.log(filter);
}
return <input value={filter} onChange={event => setFilter(event.target.value)} />;
}
ReactDOM.render(<App />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)
您必须记住渲染之间的去抖动功能。
但是,你应该不使用useCallback
记忆抖(或节流)函数在其他的答案建议。useCallback
专为内联函数设计!
而是useMemo
用来记住渲染之间的去抖动函数:
useMemo(() => debounce(loadData, 1000), []);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2496 次 |
最近记录: |