diff --git a/internal/DebounceDecorator/DebounceDecorator.js b/internal/DebounceDecorator/DebounceDecorator.js
index ddef0feac2..0fc82c3c24 100644
--- a/internal/DebounceDecorator/DebounceDecorator.js
+++ b/internal/DebounceDecorator/DebounceDecorator.js
@@ -8,7 +8,7 @@
import hoc from '@enact/core/hoc';
import {Job} from '@enact/core/util';
import PropTypes from 'prop-types';
-import {Component} from 'react';
+import {useCallback, useEffect, useRef} from 'react';
/**
* Default config for {@link sandstone/internal/DebounceDecorator.DebounceDecorator}.
@@ -60,66 +60,75 @@ const defaultConfig = {
const DebounceDecorator = hoc(defaultConfig, (config, Wrapped) => {
const {cancel, debounce, delay} = config;
- return class extends Component {
- static displayName = 'DebounceDecorator';
-
- static propTypes = /** @lends sandstone/internal/DebounceDecorator.DebounceDecorator.prototype */ {
- /**
- * Handler for `onChange` events
- *
- * `'onChange'` can be changed to a different prop name by specifying the `debounce`
- * config option.
- *
- * @see {@link sandstone/internal/DebounceDecorator.DebounceDecorator.defaultConfig#debounce}
- * @name onChange
- * @memberof sandstone/internal/DebounceDecorator.DebounceDecorator.prototype
- * @type {Function}
- * @public
- */
- [debounce]: PropTypes.func
- };
-
- constructor (props) {
- super(props);
- this.job = new Job(this.emitEvent.bind(this), delay);
- }
-
- componentWillUnmount () {
- this.job.stop();
- }
+ // eslint-disable-next-line no-shadow
+ const DebounceDecorator = (props) => {
+ let debounceProps = props;
- emitEvent (ev) {
- if (this.props[debounce]) {
- this.props[debounce](ev);
+ const emitEvent = useCallback((ev) => {
+ if (props[debounce]) {
+ props[debounce](ev);
}
- }
+ }, [props]);
- handleEvent = (ev) => {
- this.job.start(ev);
- };
+ const emitEventRef = useRef(emitEvent);
+ const job = useRef(new Job(emitEventRef.current, delay));
- handleCancel = (ev) => {
- if (this.props[cancel]) {
- this.props[cancel](ev);
+ useEffect(() => {
+ if (emitEvent !== emitEventRef.current) {
+ emitEventRef.current = emitEvent;
+ job.current.stop();
+ job.current = new Job(emitEvent, delay);
}
- this.job.stop();
- };
+ }, [emitEvent]);
- render () {
- let props = this.props;
+ useEffect(() => {
+ return () => {
+ job.current.stop();
+ };
+ }, []);
- if (debounce || cancel) {
- props = {...props};
+ const handleEvent = useCallback((ev) => {
+ job.current.start(ev);
+ }, []);
- if (debounce) props[debounce] = this.handleEvent;
- if (cancel) props[cancel] = this.handleCancel;
+ const handleCancel = useCallback((ev) => {
+ if (props[cancel]) {
+ props[cancel](ev);
}
+ job.current.stop();
+ }, [props]);
+
+ if (debounce || cancel) {
+ debounceProps = {...props};
- return (
-
- );
+ if (debounce) debounceProps[debounce] = handleEvent;
+ if (cancel) debounceProps[cancel] = handleCancel;
}
+
+ return (
+
+ );
+ };
+
+ DebounceDecorator.displayName = 'DebounceDecorator';
+
+ DebounceDecorator.propTypes = {/** @lends sandstone/internal/DebounceDecorator.DebounceDecorator.prototype */
+ /**
+ * Handler for `onChange` events
+ *
+ * `'onChange'` can be changed to a different prop name by specifying the `debounce`
+ * config option.
+ *
+ * @see {@link sandstone/internal/DebounceDecorator.DebounceDecorator.defaultConfig#debounce}
+ * @name onChange
+ * @memberof sandstone/internal/DebounceDecorator.DebounceDecorator.prototype
+ * @type {Function}
+ * @public
+ */
+ [debounce]: PropTypes.func
};
+
+ return DebounceDecorator;
});
export default DebounceDecorator;