如何在React.js中执行debounce ?
我想撤消handleOnChange。
我尝试debounce(这。handleOnChange, 200)但它不起作用。
function debounce(fn, delay) {
var timer = null;
return function() {
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}
var SearchBox = React.createClass({
render: function() {
return <input type="search" name="p" onChange={this.handleOnChange} />;
},
handleOnChange: function(event) {
// make ajax call
}
});
您可以使用Lodash debounce https://lodash.com/docs/4.17.5#debounce方法。它简单有效。
import * as lodash from lodash;
const update = (input) => {
// Update the input here.
console.log(`Input ${input}`);
}
const debounceHandleUpdate = lodash.debounce((input) => update(input), 200, {maxWait: 200});
doHandleChange() {
debounceHandleUpdate(input);
}
您还可以使用下面的方法取消debounce方法。
this.debounceHandleUpdate.cancel();
希望对你有所帮助。干杯! !
在与文本输入斗争了一段时间后,我自己没有找到一个完美的解决方案,我在npm上发现了这个:react-debounce-input。
这里有一个简单的例子:
import React from 'react';
import ReactDOM from 'react-dom';
import {DebounceInput} from 'react-debounce-input';
class App extends React.Component {
state = {
value: ''
};
render() {
return (
<div>
<DebounceInput
minLength={2}
debounceTimeout={300}
onChange={event => this.setState({value: event.target.value})} />
<p>Value: {this.state.value}</p>
</div>
);
}
}
const appRoot = document.createElement('div');
document.body.appendChild(appRoot);
ReactDOM.render(<App />, appRoot);
DebounceInput组件接受您可以分配给普通输入元素的所有道具。在codeen上试试吧
我希望这也能帮助其他人,节省他们的时间。
扩展useState钩子
import { useState } from "react";
import _ from "underscore"
export const useDebouncedState = (initialState, durationInMs = 500) => {
const [internalState, setInternalState] = useState(initialState);
const debouncedFunction = _.debounce(setInternalState, durationInMs);
return [internalState, debouncedFunction];
};
export default useDebouncedState;
使用钩
import useDebouncedState from "../hooks/useDebouncedState"
//...
const [usernameFilter, setUsernameFilter] = useDebouncedState("")
//...
<input id="username" type="text" onChange={e => setUsernameFilter(e.target.value)}></input>
https://trippingoncode.com/react-debounce-hook/
我们需要将setter传递给debpublished方法:
以下是StackBlitz的一个例子:
import React from "react";
import debounce from "lodash/debounce";
export default function App() {
const [state, setState] = React.useState({
debouncedLog: ""
});
const debouncedLog = React.useCallback(
debounce((setState, log) => {
setState(prevState => ({
...prevState,
debouncedLog: log
}));
}, 500),
[]
);
const onChange = React.useCallback(({ target: { value: log } }) => {
debouncedLog(setState, log); // passing the setState along...
}, []);
return (
<div>
<input onChange={onChange} style={{ outline: "1px blue solid" }} />
<pre>Debounced Value: {state.debouncedLog}</pre>
</div>
);
}
祝你好运…
避免使用event.persist()——你想让React回收合成事件。我认为无论你使用类还是钩子,最干净的方法是将回调函数分成两部分:
没有deboundation的回调
只使用您需要的事件片段调用已撤销的函数(这样合成的事件就可以循环使用)
类
handleMouseOver = throttle(target => {
console.log(target);
}, 1000);
onMouseOver = e => {
this.handleMouseOver(e.target);
};
<div onMouseOver={this.onMouseOver} />
功能
const handleMouseOver = useRef(throttle(target => {
console.log(target);
}, 1000));
function onMouseOver(e) {
handleMouseOver.current(e.target);
}
<div onMouseOver={this.onMouseOver} />
注意,如果你的handleMouseOver函数从组件中使用状态,你应该使用usemo而不是useRef,并将它们作为依赖项传递,否则你将使用过时的数据(当然不适用于类)。