Skip to content

Commit

Permalink
Update debounce prop of Textarea + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tcbegley committed Jan 4, 2025
1 parent df05661 commit 85dbb87
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/components/input/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const Input = props => {
if (debounce) {
if (Number.isFinite(debounce)) {
clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(onEvent, debounce * 1000);
debounceRef.current = setTimeout(onEvent, debounce);
}
} else {
onEvent();
Expand Down Expand Up @@ -604,7 +604,7 @@ Input.propTypes = {
* focus. If it's false, it will sent the value back on every
* change. If debounce is a number, the value will be sent to the
* server only after the user has stopped typing for that number
* of seconds.
* of milliseconds.
*/
debounce: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),

Expand Down
19 changes: 15 additions & 4 deletions src/components/input/Textarea.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useEffect, useState} from 'react';
import React, {useEffect, useRef, useState} from 'react';
import PropTypes from 'prop-types';
import {omit} from 'ramda';
import classNames from 'classnames';
Expand Down Expand Up @@ -43,6 +43,7 @@ const Textarea = props => {
...otherProps
} = props;
const [valueState, setValueState] = useState(value || '');
const debounceRef = useRef(null);

useEffect(() => {
if (value !== valueState) {
Expand All @@ -53,7 +54,15 @@ const Textarea = props => {
const onChange = e => {
const newValue = e.target.value;
setValueState(newValue);
if (!debounce && setProps) {
if (debounce) {
if (Number.isFinite(debounce)) {
clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(
() => setProps({value: newValue}),
debounce
);
}
} else {
setProps({value: newValue});
}
};
Expand Down Expand Up @@ -435,8 +444,10 @@ Textarea.propTypes = {
n_clicks_timestamp: PropTypes.number,

/**
* If true, changes to input will be sent back to the Dash server only on enter or when losing focus.
* If it's false, it will sent the value back on every change.
* If true, changes to input will be sent back to the Dash server only on enter or
* when losing focus. If it's false, it will sent the value back on every change.
* If debounce is a number, the value will be sent to the server only after the user
* has stopped typing for that number of milliseconds
*/
debounce: PropTypes.bool,

Expand Down
6 changes: 3 additions & 3 deletions src/components/input/__tests__/Input.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,14 @@ describe('Input', () => {
});
});

describe('debounce', () => {
describe('numeric debounce', () => {
let inputElement, mockSetProps;

beforeEach(() => {
jest.useFakeTimers();
mockSetProps = jest.fn();
const {container} = render(
<Input setProps={mockSetProps} value="" debounce={2} />
<Input setProps={mockSetProps} value="" debounce={2000} />
);
inputElement = container.firstChild;
});
Expand All @@ -215,7 +215,7 @@ describe('Input', () => {
expect(inputElement).toHaveValue('some-input-value');
act(() => jest.advanceTimersByTime(1000));
expect(mockSetProps.mock.calls).toHaveLength(0);
act(() => jest.advanceTimersByTime(4000));
act(() => jest.advanceTimersByTime(1000));
expect(mockSetProps.mock.calls).toHaveLength(1);
});
});
Expand Down
27 changes: 26 additions & 1 deletion src/components/input/__tests__/Textarea.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

import React from 'react';
import {render, fireEvent} from '@testing-library/react';
import {act, render, fireEvent} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Textarea from '../Textarea';

Expand Down Expand Up @@ -218,5 +218,30 @@ describe('Textarea', () => {
expect(mockSetProps.mock.calls).toHaveLength(1);
});
});

describe('numeric debounce', () => {
let textarea, mockSetProps;

beforeEach(() => {
jest.useFakeTimers();
mockSetProps = jest.fn();
const {container} = render(
<Textarea setProps={mockSetProps} value="" debounce={2000} />
);
textarea = container.firstChild;
});

test('call setProps after delay if debounce is number', () => {
fireEvent.change(textarea, {
target: {value: 'some-input-value'}
});
expect(mockSetProps.mock.calls).toHaveLength(0);
expect(textarea).toHaveValue('some-input-value');
act(() => jest.advanceTimersByTime(1000));
expect(mockSetProps.mock.calls).toHaveLength(0);
act(() => jest.advanceTimersByTime(1000));
expect(mockSetProps.mock.calls).toHaveLength(1);
});
});
});
});

0 comments on commit 85dbb87

Please sign in to comment.