From ecb72d3c85a49fad496ca97f470f46857131cc22 Mon Sep 17 00:00:00 2001 From: Andy Benedict Date: Wed, 6 Jul 2022 22:29:58 -0400 Subject: [PATCH 1/3] Add example for external validation with value update --- example/App.js | 7 +++++++ example/MinMax.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 example/MinMax.js diff --git a/example/App.js b/example/App.js index b331e51..62e20cc 100644 --- a/example/App.js +++ b/example/App.js @@ -4,6 +4,7 @@ import {Customizable} from './Customizable'; import {UndoRedo} from './UndoRedo'; import {Textarea} from './Textarea'; import {Ref} from './Ref'; +import {MinMax} from './MinMax'; import {DefaultValue} from './DefaultValue'; @@ -40,6 +41,12 @@ export function App() {

Example 6. Create with default value

+ +
+

Example 7. With External Validation

+ +

Accepts values between 10 and 100

+
); } diff --git a/example/MinMax.js b/example/MinMax.js new file mode 100644 index 0000000..1e63906 --- /dev/null +++ b/example/MinMax.js @@ -0,0 +1,44 @@ +import React from 'react'; +import {DebounceInput} from '../src'; + + +export class MinMax extends React.Component { + state = { + value: null + }; + + render() { + const {value} = this.state; + + const min = 10; + const max = 100; + + const handleChange = (e) => { + let newValue = Number(e.target.value); + if (newValue === 0) { + newValue = null; + } else if (newValue < min) { + newValue = min; + } else if (newValue > max) { + newValue = max; + } + this.setState({value: newValue}); + } + + return ( +
+
+ +

Value: {JSON.stringify(value)}

+
+
+ ); + } +} From abf206ef52344bccb3d06fd33f5a9f57c08457c7 Mon Sep 17 00:00:00 2001 From: Andy Benedict Date: Wed, 6 Jul 2022 22:34:37 -0400 Subject: [PATCH 2/3] Set isDebouncing flag before first render on update When migrating from componentWillReceiveProps to componentDidUpdate the initial state update on the first keypress was being processed before the isDebouncing flag was set. In order to combat hitting a check that the isDebouncing flag was intended to avoid, an additional check was added that causes undesirable rendering behavior in certain cases where the internal state can get out of sync with the external values, especially during external validation that might want to update the component's value prop. To mitigate, we need to set the isDebouncing flag before we set the initial state. --- src/Component.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Component.js b/src/Component.js index ed92b0e..e399bbb 100644 --- a/src/Component.js +++ b/src/Component.js @@ -56,7 +56,7 @@ export class DebounceInput extends React.PureComponent { const {debounceTimeout: oldTimeout, value: oldValue} = prevProps; const {value: stateValue} = this.state; - if (typeof value !== 'undefined' && oldValue !== value && stateValue !== value) { + if (typeof value !== 'undefined' && stateValue !== value) { // Update state.value if new value passed via props, yep re-render should happen // eslint-disable-next-line react/no-did-update-set-state this.setState({value}); @@ -78,8 +78,9 @@ export class DebounceInput extends React.PureComponent { event.persist(); const {value: oldValue} = this.state; - const {minLength} = this.props; + const {debounceTimeout, minLength} = this.props; + if (debounceTimeout > 0) this.isDebouncing = true; this.setState({value: event.target.value}, () => { const {value} = this.state; @@ -132,7 +133,6 @@ export class DebounceInput extends React.PureComponent { }, debounceTimeout); this.notify = event => { - this.isDebouncing = true; debouncedChangeFunc(event); }; From 1fe23117d234b14ee2e1232613fc05c348a84d46 Mon Sep 17 00:00:00 2001 From: Andy Benedict Date: Thu, 7 Jul 2022 09:14:47 -0400 Subject: [PATCH 3/3] Correct lint errors --- example/App.js | 10 +++---- example/MinMax.js | 68 +++++++++++++++++++++++------------------------ src/Component.js | 2 +- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/example/App.js b/example/App.js index 62e20cc..49bd9ed 100644 --- a/example/App.js +++ b/example/App.js @@ -42,11 +42,11 @@ export function App() { -
-

Example 7. With External Validation

- -

Accepts values between 10 and 100

-
+
+

Example 7. With External Validation

+ +

Accepts values between 10 and 100

+
); } diff --git a/example/MinMax.js b/example/MinMax.js index 1e63906..68a615a 100644 --- a/example/MinMax.js +++ b/example/MinMax.js @@ -3,42 +3,42 @@ import {DebounceInput} from '../src'; export class MinMax extends React.Component { - state = { - value: null - }; + state = { + value: null + }; - render() { - const {value} = this.state; + render() { + const {value} = this.state; - const min = 10; - const max = 100; + const min = 10; + const max = 100; - const handleChange = (e) => { - let newValue = Number(e.target.value); - if (newValue === 0) { - newValue = null; - } else if (newValue < min) { - newValue = min; - } else if (newValue > max) { - newValue = max; - } - this.setState({value: newValue}); - } + const handleChange = e => { + let newValue = Number(e.target.value); + if (newValue === 0) { + newValue = null; + } else if (newValue < min) { + newValue = min; + } else if (newValue > max) { + newValue = max; + } + this.setState({value: newValue}); + }; - return ( -
-
- -

Value: {JSON.stringify(value)}

-
-
- ); - } + return ( +
+
+ +

Value: {JSON.stringify(value)}

+
+
+ ); + } } diff --git a/src/Component.js b/src/Component.js index e399bbb..8212445 100644 --- a/src/Component.js +++ b/src/Component.js @@ -53,7 +53,7 @@ export class DebounceInput extends React.PureComponent { } const {value, debounceTimeout} = this.props; - const {debounceTimeout: oldTimeout, value: oldValue} = prevProps; + const {debounceTimeout: oldTimeout} = prevProps; const {value: stateValue} = this.state; if (typeof value !== 'undefined' && stateValue !== value) {