From 424c75029c23838b1ac95007eb190bbafc3a2957 Mon Sep 17 00:00:00 2001 From: Sudhanshu Date: Sun, 3 Sep 2023 20:56:01 +0530 Subject: [PATCH] - Fix infinite rerender when values.value is used valueIsNumericString not provided. #786 --- documentation/v5/docs/props.md | 4 +-- src/numeric_format.tsx | 4 +-- test/library/input_numeric_format.spec.js | 39 ++++++++++++++++++++++- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/documentation/v5/docs/props.md b/documentation/v5/docs/props.md index 8cdbd9ae..a75b793c 100644 --- a/documentation/v5/docs/props.md +++ b/documentation/v5/docs/props.md @@ -162,7 +162,7 @@ const MAX_LIMIT = 1000; **default**: false -If value is passed as string representation of numbers (unformatted) and number is used in any format props like in prefix or suffix in numeric format and format prop in pattern format then this should be passed as `true`. +If value is passed as string representation of numbers (unformatted) and thousandSeparator is `.` in numeric format or number is used in any format props like in prefix or suffix in numeric format and format prop in pattern format then this should be passed as `true`. **Note**: Prior to 5.2.0 its was always required to be passed as true when value is passed as string representation of numbers (unformatted). @@ -192,7 +192,7 @@ import { PatternFormat } from 'react-number-format'; This handler provides access to any values changes in the input field and is triggered only when a prop changes or the user input changes. It provides two arguments namely the [valueObject](quirks#values-object) as the first and the [sourceInfo](quirks#sourceInfo) as the second. The [valueObject](quirks#values-object) parameter contains the `formattedValue`, `value` and the `floatValue` of the given input field. The [sourceInfo](quirks#sourceInfo) contains the `event` Object and a `source` key which indicates whether the triggered change is due to an event or a prop change. This is particularly useful in identify whether the change is user driven or is an uncontrolled change due to any prop value being updated. :::info -If you are using `values.value` which is non formatted value as numeric string. Make sure to pass valueIsNumericString to be true if any of the format prop has number on it. See [valueIsNumericString](#valueisnumericstring-boolean) for more details. +If you are using `values.value` which is non formatted value as numeric string. Make sure to pass valueIsNumericString to be true if any of the format prop has number on it, or if thousandSeparator is `.` in NumericFormat . See [valueIsNumericString](#valueisnumericstring-boolean) for more details. ::: ```js diff --git a/src/numeric_format.tsx b/src/numeric_format.tsx index c3e2416e..aa35cc98 100644 --- a/src/numeric_format.tsx +++ b/src/numeric_format.tsx @@ -371,9 +371,9 @@ export function useNumericFormat( let _valueIsNumericString = valueIsNumericString ?? isNumericString(_value, prefix, suffix); if (!isNil(value)) { - _valueIsNumericString = valueIsNumericString || typeof value === 'number'; + _valueIsNumericString = _valueIsNumericString || typeof value === 'number'; } else if (!isNil(defaultValue)) { - _valueIsNumericString = valueIsNumericString || typeof defaultValue === 'number'; + _valueIsNumericString = _valueIsNumericString || typeof defaultValue === 'number'; } const roundIncomingValueToPrecision = (value: string | number | null | undefined) => { diff --git a/test/library/input_numeric_format.spec.js b/test/library/input_numeric_format.spec.js index 04d09b55..ff6278b1 100644 --- a/test/library/input_numeric_format.spec.js +++ b/test/library/input_numeric_format.spec.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import ReactDOM from 'react-dom'; import NumericFormat from '../../src/numeric_format'; @@ -694,6 +694,43 @@ describe('Test NumberFormat as input with numeric format options', () => { expect(input.value).toEqual('12,345'); }); + it('should not infinite rerender when valueIsNumericString is not set and decimalScale is provided, and values.value is used inside onValueChange #786', async () => { + const ControlledComponent = (props) => { + const [value, setValue] = useState(''); + const [renderCount, setRenderCount] = useState(0); + + return ( + <> + { + //return to avoid infinite rerender + if (renderCount > 10) return; + setValue(values.value); + setRenderCount(renderCount + 1); + }} + {...props} + /> + {renderCount} + + ); + }; + const { input, view } = await render( + , + ); + + simulateNativeKeyInput(input, '2', 0, 0); + + const renderCount = await view.getByTestId('renderCount'); + expect(renderCount.innerHTML).toEqual('1'); + expect(input.value).toEqual('2,00'); + }); + describe('should allow typing number if prefix or suffix is just an number #691', () => { it('when prefix is number', async () => { const { input } = await render();