我正在尝试 React Native 和 lodash 的 debounce。
使用以下代码只会使其像延迟一样工作,而不是去抖。
<Input
onChangeText={(text) => {
_.debounce(()=> console.log("debouncing"), 2000)()
}
/>
如果我输入“foo”这样的输入,我希望控制台仅记录一次去抖动。现在它记录“debounce”3次。
Debounce 函数应该在 render 方法之外的某个地方定义,因为每次调用它时它都必须引用该函数的同一个实例,而不是创建一个新实例,就像现在将它放入
onChangeText
处理函数中时发生的情况一样.
定义去抖函数的最常见位置是在组件的对象上。这是一个例子:
class MyComponent extends React.Component {
constructor() {
this.onChangeTextDelayed = _.debounce(this.onChangeText, 2000);
}
onChangeText(text) {
console.log("debouncing");
}
render() {
return <Input onChangeText={this.onChangeTextDelayed} />
}
}
使用“useCallback”反应钩子
在尝试了许多不同的方法之后,我发现使用“useCallback”是解决多个调用问题最简单、最有效的方法。
根据 Hooks API 文档,“useCallback 返回回调的记忆版本,仅当依赖项之一发生更改时该版本才会更改。”
将空数组作为依赖项传递可确保回调仅被调用一次。这是一个简单的实现。
import React, { useCallback } from "react";
import { debounce } from "lodash";
const handler = useCallback(debounce(someFunction, 2000), []);
const onChange = (event) => {
// perform any event related action here
handler();
};
正如其他答案已经指出的那样,去抖函数引用必须创建一次,并通过调用相同的引用来谴责相关函数(即我的示例中的
changeTextDebounced
)。
首先要导入
import {debounce} from 'lodash';
对于类组件
class SomeClassComponent extends React.Component {
componentDidMount = () => {
this.changeTextDebouncer = debounce(this.changeTextDebounced, 500);
}
changeTextDebounced = (text) => {
console.log("debounced");
}
render = () => {
return <Input onChangeText={this.changeTextDebouncer} />;
}
}
对于功能组件
const SomeFnComponent = () => {
const changeTextDebouncer = useCallback(debounce(changeTextDebounced, 500), []);
const changeTextDebounced = (text) => {
console.log("debounced");
}
return <Input onChangeText={changeTextDebouncer} />;
}
功能组件工作方案:
import {debounce} from 'lodash';
const [text, settext] = useState('');
<TextInput
style={styles.textInput}
numberOfLines={1}
placeholder={placeholder}
placeholderTextColor={COLOR_GRAY_510}
onChangeText={handleChange}
value={text}
/>
----------------------------------------------
const handleChange = async textParam => {
settext(textParam);
debounceCall(textParam);
};
const debounceCall = useCallback(
debounce(textParam => {
searchAPICall(textParam);
}, 500),
[],
);
const searchAPICall = async textParam => {
if (textParam.length > 2) {
let suggestions = await suggestAddressList(textParam);
setresultList(suggestions.length > 0 ? suggestions : []);
} else {
setresultList([]);
}
};
我在 textInput 中遇到了同样的问题,我的正则表达式被调用了太多次。我使用下面的代码来避免这个问题:
const emailReg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w\w+)+$/;
const debounceReg = useCallback(debounce((text: string) => {
if (emailReg.test(text)) {
setIsValidEmail(true);
} else {
setIsValidEmail(false);
}
}, 800), []);
const onChangeHandler = (text: string) => {
setEmailAddress(text);
debounceReg(text)
};
我的 utils 中的去抖代码是
function debounce<Params extends any[]>(
f: (...args: Params) => any,
delay: number,
): (...args: Params) => void {
let timer: NodeJS.Timeout;
return (...args: Params) => {
clearTimeout(timer);
timer = setTimeout(() => {
f(...args);
}, delay);
};
}