Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: manipulating controlled input value breaks native validation #27621

Closed
HugeLetters opened this issue Oct 29, 2023 · 5 comments
Closed

Bug: manipulating controlled input value breaks native validation #27621

HugeLetters opened this issue Oct 29, 2023 · 5 comments
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@HugeLetters
Copy link

If you have a controlled input with some restrictions(like minLength for example) manipulating input value in any way in onChange handler breaks native validation.
For example if you have onChange={e => setText(e.target.value.toUpperCase())}} this will break if your value after applying uppercase is different than the initial target value. So an input like "123" works but "a" doesn't - in the latter example HTML will consider input value to be valid.

React version:
18.0.0

Steps To Reproduce

You can check-out code example below which showcases the issue - if you input any letter the background will turn green immediately indicating the the value is valid even though it doesn't meet minLengh requirement. If you input a number instead it works as intended(because "1" is the same as "1".toUpperCase())

Link to code example:
https://playcode.io/1645770

The current behavior

Explained above

The expected behavior

It should handle validation correctly as with regular input

@HugeLetters HugeLetters added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Oct 29, 2023
@felipe-rodolfo
Copy link

In the example you provided, you are using React to create a text input component that converts the entered text to uppercase. However, you have noticed that this can interfere with the native HTML validation, especially when the input does not meet validation requirements, as in the case of "a". This happens because the actual value of the input is not altered; only the value displayed in the user interface is changed.

To work around this issue, you can use the onInput event instead of the onChange event. The onInput event is triggered whenever the value of the input field is modified, whereas the onChange event may be triggered after the input field loses focus, which is not ideal for real-time validation.

@HugeLetters
Copy link
Author

HugeLetters commented Oct 31, 2023

@felipe-rodolfo React's onChange handler is actually an onInput handler, React doesn't have have an actual onChange handler. So they behave the same way.
image

Also if onChange handler would have worked like you described - my playground would work correctly since handler wouldn't fire while I'm typing stuff into the input until I unfocus/press enter etc. That's not what happens for the reasons described above.

@felipe-rodolfo
Copy link

You are correct, and I apologize for any confusion. React's documentation does indicate that onInput fires immediately when the value is changed by the user, and it is considered idiomatic in React to use onChange instead, as it works similarly.

In most cases, using onChange in a controlled component is the appropriate choice, and it should behave as expected for real-time input handling. The issue you were experiencing with the validation may be specific to how transformations were applied in your onChange handler.

To address the validation issue you initially described, you may need to adjust how you handle transformations in the onChange handler or consider other approaches. Using onChange itself is not the problem; it's about making sure your transformations and validation logic are compatible with the controlled component's behavior.

to solve the validation issue when converting text to uppercase while still using the onChange event, you can follow this approach:

Keep using the onChange event to update the component state and convert the text to uppercase.

Add a custom validation function that checks if the value meets the requirements, such as the minimum length, within the onChange event.

Use setCustomValidity to set up custom validation based on the established rules.

Here's a modified code example:

import React from 'react';`

export function App(props) {
  const [text, setText] = React.useState('');

  const handleInputChange = (e) => {
    const inputText = e.target.value.toUpperCase();
    setText(inputText);

    // Custom validation function
    const isValid = inputText.length === 6;

    if (isValid) {
      e.target.setCustomValidity('');
    } else {
      e.target.setCustomValidity('The text must have 6 characters.');
    }
  };

  return (
    <div className="App">
      <input
        value={text}
        onChange={handleInputChange}
        minLength={6}
        maxLength={6}
        required
      />
      <div>{text}</div>
    </div>
  );
} 

@HugeLetters
Copy link
Author

Could you please not clutter the issue with chatGPT responses?

@HugeLetters
Copy link
Author

Dunno why but I haven't bothered checking if it works the same way with vanilla JS and HTML - and it has the same error

https://codepen.io/HugeLetters/pen/WNWOyeG

@HugeLetters HugeLetters closed this as not planned Won't fix, can't repro, duplicate, stale Mar 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

2 participants