17 javascript ecmascript-6 lodash reactjs debounce
最好先看看我的代码:
import React, { Component } from 'react';
import _ from 'lodash';
import Services from 'Services'; // Webservice calls
export default class componentName extends Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value || null
}
}
onChange(value) {
this.setState({ value });
// This doesn't call Services.setValue at all
_.debounce(() => Services.setValue(value), 1000);
}
render() {
return (
<div>
<input
onChange={(event, value) => this.onChange(value)}
value={this.state.value}
/>
</div>
)
}
}
Run Code Online (Sandbox Code Playgroud)
只是一个简单的输入.在构造函数中,它value从道具(如果可用)中获取组件的本地状态.
然后在I 的onChange函数中input更新状态,然后尝试调用webservice端点来设置新值Services.setValue().
如果我debounce直接通过onChange输入设置,那么工作是什么:
<input
value={this.state.value}
onChange={_.debounce((event, value) => this.onChange(value), 1000)}
/>
Run Code Online (Sandbox Code Playgroud)
但是this.setState每1000毫秒只调用一次并更新视图.因此,在文本字段中输入最终看起来很奇怪,因为您键入的内容仅在稍后显示.
在这种情况下我该怎么办?
Shu*_*tri 35
出现此问题是因为您没有调用去抖功能,您可以通过以下方式进行操作
export default class componentName extends Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value || null
}
this.servicesValue = _.debounce(this.servicesValue, 1000);
}
onChange(value) {
this.setState({ value });
this.servicesValue(value);
}
servicesValue = (value) => {
Services.setValue(value)
}
render() {
return (
<div>
<input
onChange={(event, value) => this.onChange(value)}
value={this.state.value}
/>
</div>
)
}
}
Run Code Online (Sandbox Code Playgroud)
god*_*rry 15
对于那些因为油门 / 去抖动不起作用而来到这里的人的解决方案FunctionComponent- 您需要通过useRef()存储去抖动函数:
export const ComponentName = (value = null) => {
const [inputValue, setInputValue] = useState(value);
const setServicesValue = value => Services.setValue(value);
const setServicesValueDebounced = useRef(_.debounce(setServicesValue, 1000));
const handleChange = ({ currentTarget: { value } }) => {
setInputValue(value);
setServicesValueDebounced.current(value);
};
return <input onChange={handleChange} value={inputValue} />;
};
Run Code Online (Sandbox Code Playgroud)
这篇中等文章完美地解释了会发生什么:
函数内的局部变量在每次调用后都会过期。每次重新评估组件时,局部变量都会再次初始化。Throttle 和 debounce
window.setTimeout()在幕后使用。每次评估函数组件时,您都在注册一个新的setTimeout回调。所以我们将使用useRef()钩子,因为useRef()每次执行功能组件时都不会重新评估返回的值。唯一的不便是您必须通过该.current属性访问您的储值。
我创建了带有小包和包的沙箱,因此您可以对两者进行试验并选择合适的行为lodash.throttlelodash.debounce
对于 React 功能组件,默认情况下 debounce 不起作用。您必须执行以下操作才能使其正常工作:
const debouncedFunction= React.useCallback(debounce(functionToCall, 400), []);
Run Code Online (Sandbox Code Playgroud)
useCallback 使用 debounce 返回的函数并按预期工作。虽然,当您想在去抖动函数中使用状态变量时,这会稍微复杂一些(通常是这种情况)。
React.useCallback(debounce(fn, timeInMs), [])
Run Code Online (Sandbox Code Playgroud)
React.useCallback 的第二个参数是依赖项。如果您想在去抖动函数中使用 state 或 prop 变量,默认情况下,它使用旧版本的 state 变量,这将导致您的函数使用变量的历史值,这不是您需要的。要解决此问题,您必须像在 React.useEffect 中那样包含状态变量,如下所示:
React.useCallback(debounce(fn, timeInMs), [stateVariable1, stateVariable2])
Run Code Online (Sandbox Code Playgroud)
此实现可能会解决您的目的。但是您会注意到,每当状态变量(stateVariable1、stateVariable2)随着依赖项的变化而传递时,都会调用 debounced 函数。这可能不是您需要的,尤其是在使用输入字段等受控组件时。
我意识到的最佳解决方案是花一些时间将功能组件更改为基于类的组件并使用以下实现:
constructor(props)
{
super();
this.state = {...};
this.functionToCall= debounce(this.functionToCall.bind(this), 400, {'leading': true});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10762 次 |
| 最近记录: |