如何在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
}
});
下面是一个使用@Abra方法封装在函数组件中的代码片段
(我们使用织物的UI,只是用一个简单的按钮替换它)
import React, { useCallback } from "react";
import { debounce } from "lodash";
import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button';
const debounceTimeInMS = 2000;
export const PrimaryButtonDebounced = (props) => {
const debouncedOnClick = debounce(props.onClick, debounceTimeInMS, { leading: true });
const clickHandlerDebounced = useCallback((e, value) => {
debouncedOnClick(e, value);
},[]);
const onClick = (e, value) => {
clickHandlerDebounced(e, value);
};
return (
<PrimaryButton {...props}
onClick={onClick}
/>
);
}
你也可以使用自己编写的mixin,就像这样:
var DebounceMixin = {
debounce: function(func, time, immediate) {
var timeout = this.debouncedTimeout;
if (!timeout) {
if (immediate) func();
this.debouncedTimeout = setTimeout(function() {
if (!immediate) func();
this.debouncedTimeout = void 0;
}.bind(this), time);
}
}
};
然后像这样在你的组件中使用它:
var MyComponent = React.createClass({
mixins: [DebounceMixin],
handleClick: function(e) {
this.debounce(function() {
this.setState({
buttonClicked: true
});
}.bind(this), 500, true);
},
render: function() {
return (
<button onClick={this.handleClick}></button>
);
}
});
不受控制的组件
你可以使用event.persist()方法。
下面是一个使用下划线_.debounce()的例子:
var SearchBox = React.createClass({
componentWillMount: function () {
this.delayedCallback = _.debounce(function (event) {
// `event.target` is accessible now
}, 1000);
},
onChange: function (event) {
event.persist();
this.delayedCallback(event);
},
render: function () {
return (
<input type="search" onChange={this.onChange} />
);
}
});
编辑:请看这个JSFiddle
控制组件
更新:上面的例子显示了一个不受控制的组件。我一直在使用受控元素,这里是上面的另一个例子,但没有使用event.persist()“欺骗”。
JSFiddle也是可用的。不带下划线的示例
var SearchBox = React.createClass({
getInitialState: function () {
return {
query: this.props.query
};
},
componentWillMount: function () {
this.handleSearchDebounced = _.debounce(function () {
this.props.handleSearch.apply(this, [this.state.query]);
}, 500);
},
onChange: function (event) {
this.setState({query: event.target.value});
this.handleSearchDebounced();
},
render: function () {
return (
<input type="search"
value={this.state.query}
onChange={this.onChange} />
);
}
});
var Search = React.createClass({
getInitialState: function () {
return {
result: this.props.query
};
},
handleSearch: function (query) {
this.setState({result: query});
},
render: function () {
return (
<div id="search">
<SearchBox query={this.state.result}
handleSearch={this.handleSearch} />
<p>You searched for: <strong>{this.state.result}</strong></p>
</div>
);
}
});
React.render(<Search query="Initial query" />, document.body);
编辑:更新示例和JSFiddles到React 0.12
编辑:更新的例子,以解决Sebastien Lorber提出的问题
编辑:更新的jsfiddle不使用下划线和使用纯javascript debounce。
我们需要将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>
);
}
祝你好运…