I could not figure this out. Eventually created a code sandbox to try and isolate the issue and found that even stripped down, the issue persists.
I have a controlled input that should not allow the space character. e.target.value.trim()
correctly trims the space characters when the state is stored as a string but allows them when the state is part of an object.
So this works correctly:
const [primitivestring, setPrimitiveString] = useState("");
...
<input
value={primitivestring}
onChange={(e) => {
const trimmedValue = e.target.value.trim();
setPrimitiveString(trimmedValue);
}}
/>
But this does not:
const [newuserState, setnewuserState] = useState({ email: "" });
...
<input
placeholder="Email address/Username"
id="email"
type="email"
value={newuserState.email}
onChange={(e) => {
const trimmedValue = e.target.value.trim();
console.log({
trimmedValue,
trimmedValueLength: trimmedValue.length
});
setnewuserState({ ...newuserState, email: trimmedValue });
}}
/>
Link to code sandbox: https://codesandbox.io/s/sharp-hugle-7cw6tv?file=/src/App.js:353-772
Why is this happening?
Another quirk (and secondary question) - the character counter for the 'buggy' input does not update when a space character is typed BUT it does update the count (including the space characters) when a non-space character is eventually typed. Why?
Update - As per the accepted answer, the issue was to do with type="email"
and entirely unrelated to how the value in question is being stored in state. Still unclear why this issue is as it is. This thread touches on it: https://github.com/facebook/react/issues/6368 - if anybody has more info or a clear explanation, I would love to know more.
CodePudding user response:
The type="email"
is throwing things off. Emails cannot have spaces, so it looks like React, when it sees an input field of type email where the value has a space, does not fire its onChange
handler because the input is invalid.
Remove the type="email"
and it'll work as expected.
the character counter for the 'buggy' input does not update when a space character is typed BUT it does update the count (including the space characters) when a non-space character is eventually typed. Why?
Same reason - if the value has a space, it's not a valid email, so the handler doesn't fire.
function App() {
const [primitivestring, setPrimitiveString] = React.useState("");
const [newuserState, setnewuserState] = React.useState({ email: "" });
return (
<div className="App">
<h1>Sample input component</h1>
<h2>Spaces should be trimmed but are not</h2>
<input
placeholder="Email address/Username"
id="email"
value={newuserState.email}
onChange={(e) => {
const trimmedValue = e.target.value.trim();
setnewuserState({ email: trimmedValue });
}}
/>
</div>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>