s-yadav / react-number-format

React component to format numbers in an input or as a text.
MIT License
3.87k stars 409 forks source link

Removing last number with trailing zeros deletes all the right side zeros, when integrating with `react-hook-form` #835

Open pedroapfilho opened 6 months ago

pedroapfilho commented 6 months ago

Describe the issue and the actual behavior

Currently, while integrating a NumberFormatBase with useNumericFormat, and using react-number-format, there's one edge case where we need the value to be a number, and when we type something like 10.10001 and then backspace, it goes to 10.1, and not to 10.000, as expected.

https://github.com/s-yadav/react-number-format/assets/13142568/4b48c489-0c3b-4388-b400-4902fbdc1ffd

Provide a CodeSandbox link illustrating the issue

https://codesandbox.io/p/sandbox/flamboyant-poitras-c7nkld?file=%2Fsrc%2FApp.js%3A24%2C1

Provide steps to reproduce this issue

Type backspace on the input

Please check the browsers where the issue is seen

pedroapfilho commented 6 months ago

UPDATE: I can reproduce it without react-hook-form

https://codesandbox.io/p/sandbox/flamboyant-poitras-forked-jjkxkz?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clutsy9gl00063b6lxn9klv4b%2522%252C%2522sizes%2522%253A%255B100%252C0%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clutsy9gl00023b6l9hc8fr4u%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clutsy9gl00033b6lnli4rmui%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clutsy9gl00053b6l8jchf8cd%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clutsy9gl00023b6l9hc8fr4u%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clutsy9gk00013b6l8fbckltd%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252Fsrc%252Findex.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%252C%257B%2522id%2522%253A%2522clutt4js200023b6lyh1zg7r5%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522initialSelections%2522%253A%255B%257B%2522startLineNumber%2522%253A24%252C%2522startColumn%2522%253A16%252C%2522endLineNumber%2522%253A24%252C%2522endColumn%2522%253A16%257D%255D%252C%2522filepath%2522%253A%2522%252Fsrc%252FApp.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%255D%252C%2522id%2522%253A%2522clutsy9gl00023b6l9hc8fr4u%2522%252C%2522activeTabId%2522%253A%2522clutt4js200023b6lyh1zg7r5%2522%257D%252C%2522clutsy9gl00053b6l8jchf8cd%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clutsy9gl00043b6lojubw3uv%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clutsy9gl00053b6l8jchf8cd%2522%252C%2522activeTabId%2522%253A%2522clutsy9gl00043b6lojubw3uv%2522%257D%252C%2522clutsy9gl00033b6lnli4rmui%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clutsy9gl00033b6lnli4rmui%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Afalse%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D

pedroapfilho commented 6 months ago

UPDATE: This issue didn't happen on the version 4.9.1: https://codesandbox.io/p/sandbox/flamboyant-poitras-forked-w238km?file=%2Fsrc%2FApp.js%3A2%2C21&layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clutsy9gl00063b6lxn9klv4b%2522%252C%2522sizes%2522%253A%255B100%252C0%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clutsy9gl00023b6l9hc8fr4u%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clutsy9gl00033b6lnli4rmui%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clutsy9gl00053b6l8jchf8cd%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clutsy9gl00023b6l9hc8fr4u%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clutsy9gk00013b6l8fbckltd%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252Fsrc%252Findex.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%252C%257B%2522id%2522%253A%2522clutt4js200023b6lyh1zg7r5%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522initialSelections%2522%253A%255B%257B%2522startLineNumber%2522%253A2%252C%2522startColumn%2522%253A21%252C%2522endLineNumber%2522%253A2%252C%2522endColumn%2522%253A21%257D%255D%252C%2522filepath%2522%253A%2522%252Fsrc%252FApp.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%255D%252C%2522id%2522%253A%2522clutsy9gl00023b6l9hc8fr4u%2522%252C%2522activeTabId%2522%253A%2522clutt4js200023b6lyh1zg7r5%2522%257D%252C%2522clutsy9gl00053b6l8jchf8cd%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clutsy9gl00043b6lojubw3uv%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clutsy9gl00053b6l8jchf8cd%2522%252C%2522activeTabId%2522%253A%2522clutsy9gl00043b6lojubw3uv%2522%257D%252C%2522clutsy9gl00033b6lnli4rmui%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clutsy9gl00033b6lnli4rmui%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Afalse%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D

pedroapfilho commented 6 months ago

UPDATE: it seems that removing these lines make it work as expected: https://github.com/s-yadav/react-number-format/blob/master/src/utils.tsx#L516-L528

s-yadav commented 6 months ago

Hey @pedroapfilho, the issue is that RNF currently works partially controlled and partially uncontrolled way. And in this case, when used floatValue on the state, 10.10000 is actually treated as just 10.1 in javascript numbers. So basically the value prop is coming back as 10.1 updating the rendered input. Try pasting 10.10000 in console, it would be printed as 10.1

Prior to v5 it used to work, because we were comparing floatValue coming from prop and floatValue inside the state, if that not changed we were not rendering the input. But that had some other bugs.

To unblock yourself, I would suggest that for state management use a numeric string value and on submit convert it to a number, Or you can have a custom component which manages the string state and passes the numeric value to parent. Here's an example: https://codesandbox.io/p/sandbox/flamboyant-poitras-forked-4j4rzs?file=%2Fsrc%2FApp.js%3A30%2C42

pedroapfilho commented 6 months ago

Doing it this way introduces some other bugs, in the end it was flaky, and didn't pass the tests that were created to prior. It would be nice to have it fixecd on v6. I'm willing to sponsor the project to make it happen.