如何在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
}
});
对于debounce,你需要在event.persist()中保留原始的合成事件。下面是用React 16+测试的工作示例。
import React, { Component } from 'react';
import debounce from 'lodash/debounce'
class ItemType extends Component {
evntHandler = debounce((e) => {
console.log(e)
}, 500);
render() {
return (
<div className="form-field-wrap"
onClick={e => {
e.persist()
this.evntHandler(e)
}}>
...
</div>
);
}
}
export default ItemType;
使用功能组件,您可以做到这一点-
const Search = ({ getBooks, query }) => {
const handleOnSubmit = (e) => {
e.preventDefault();
}
const debouncedGetBooks = debounce(query => {
getBooks(query);
}, 700);
const onInputChange = e => {
debouncedGetBooks(e.target.value)
}
return (
<div className="search-books">
<Form className="search-books--form" onSubmit={handleOnSubmit}>
<Form.Group controlId="formBasicEmail">
<Form.Control type="text" onChange={onInputChange} placeholder="Harry Potter" />
<Form.Text className="text-muted">
Search the world's most comprehensive index of full-text books.
</Form.Text>
</Form.Group>
<Button variant="primary" type="submit">
Search
</Button>
</Form>
</div>
)
}
引用- - - - - -
——https://gist.github.com/elijahmanor/08fc6c8468c994c844213e4a4344a709
——https://blog.revathskumar.com/2016/02/reactjs-using-debounce-in-react-components.html
2022 -使用useEffect钩子
此时最好的选择是使用useEffect钩子。useEffect允许您设置一个函数,该函数可以修改状态以响应某些异步事件。debounging是异步的,因此useEffect可以很好地用于此目的。
如果从钩子返回一个函数,返回的函数将在钩子再次被调用之前被调用。这让您可以取消之前的超时,有效地解除函数。
例子
这里我们有两个状态,value和tempValue。设置tempValue将触发useEffect钩子,该钩子将启动一个1000ms超时,该超时将调用一个函数将tempValue复制为value。
钩子返回一个取消定时器设置的函数。当钩子再次被调用时(即按下另一个键),超时被取消并重置。
const DebounceDemo = () => {
const [value, setValue] = useState();
const [tempValue, setTempValue] = useState();
// This hook will set a 1000 ms timer to copy tempValue into value
// If the hook is called again, the timer will be cancelled
// This creates a debounce
useEffect(
() => {
// Wait 1000ms before copying the value of tempValue into value;
const timeout = setTimeout(() => {
setValue(tempValue);
}, 1000);
// If the hook is called again, cancel the previous timeout
// This creates a debounce instead of a delay
return () => clearTimeout(timeout);
},
// Run the hook every time the user makes a keystroke
[tempValue]
)
// Here we create an input to set tempValue.
// value will be updated 1000 ms after the hook is last called,
// i.e after the last user keystroke.
return (
<>
<input
onChange={
({ target }) => setTempValue(target.value)
}
/>
<p>{ value }</p>
</>
)
}
你试过吗?
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) {
debounce(\\ Your handleChange code , 200);
}
});
Julen的解决方案有点难以阅读,这里有更清晰和准确的反应代码,供那些根据标题而不是问题的微小细节绊倒他的人使用。
Tl;dr版本:当你要更新到观察者发送调用一个调度方法,反过来实际上会通知观察者(或执行ajax等)
使用示例组件jsfiddle完成jsfiddle
var InputField = React.createClass({
getDefaultProps: function () {
return {
initialValue: '',
onChange: null
};
},
getInitialState: function () {
return {
value: this.props.initialValue
};
},
render: function () {
var state = this.state;
return (
<input type="text"
value={state.value}
onChange={this.onVolatileChange} />
);
},
onVolatileChange: function (event) {
this.setState({
value: event.target.value
});
this.scheduleChange();
},
scheduleChange: _.debounce(function () {
this.onChange();
}, 250),
onChange: function () {
var props = this.props;
if (props.onChange != null) {
props.onChange.call(this, this.state.value)
}
},
});
有一个使用react钩子的简单方法。
步骤1:定义一个状态来维护搜索的文本
const [searchTerm, setSearchTerm] = useState('')
步骤2:使用useEffect捕获搜索Term中的任何变化
useEffect(() => {
const delayDebounceFn = setTimeout(() => {
if (searchTerm) {
// write your logic here
}
}, 400)
return () => clearTimeout(delayDebounceFn)
}, [searchTerm])
步骤3:编写一个函数来处理输入更改
function handleInputChange(value) {
if (value) {
setSearchTerm(value)
}
}
就这些!在需要时调用此方法
至于2021年6月,您可以简单地实现xnimorz解决方案:https://github.com/xnimorz/use-debounce
import { useState, useEffect, useRef } from "react";
// Usage
function App() {
// State and setters for ...
// Search term
const [searchTerm, setSearchTerm] = useState("");
// API search results
const [results, setResults] = useState([]);
// Searching status (whether there is pending API request)
const [isSearching, setIsSearching] = useState(false);
// Debounce search term so that it only gives us latest value ...
// ... if searchTerm has not been updated within last 500ms.
// The goal is to only have the API call fire when user stops typing ...
// ... so that we aren't hitting our API rapidly.
const debouncedSearchTerm = useDebounce(searchTerm, 500);
// Effect for API call
useEffect(
() => {
if (debouncedSearchTerm) {
setIsSearching(true);
searchCharacters(debouncedSearchTerm).then((results) => {
setIsSearching(false);
setResults(results);
});
} else {
setResults([]);
setIsSearching(false);
}
},
[debouncedSearchTerm] // Only call effect if debounced search term changes
);
return (
<div>
<input
placeholder="Search Marvel Comics"
onChange={(e) => setSearchTerm(e.target.value)}
/>
{isSearching && <div>Searching ...</div>}
{results.map((result) => (
<div key={result.id}>
<h4>{result.title}</h4>
<img
src={`${result.thumbnail.path}/portrait_incredible.${result.thumbnail.extension}`}
/>
</div>
))}
</div>
);
}
// API search function
function searchCharacters(search) {
const apiKey = "f9dfb1e8d466d36c27850bedd2047687";
return fetch(
`https://gateway.marvel.com/v1/public/comics?apikey=${apiKey}&titleStartsWith=${search}`,
{
method: "GET",
}
)
.then((r) => r.json())
.then((r) => r.data.results)
.catch((error) => {
console.error(error);
return [];
});
}
// Hook
function useDebounce(value, delay) {
// State and setters for debounced value
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(
() => {
// Update debounced value after delay
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
// Cancel the timeout if value changes (also on delay change or unmount)
// This is how we prevent debounced value from updating if value is changed ...
// .. within the delay period. Timeout gets cleared and restarted.
return () => {
clearTimeout(handler);
};
},
[value, delay] // Only re-call effect if value or delay changes
);
return debouncedValue;
}