Say I'm building a controlled React <NumInput />
element that returns <input type="number" value={this.props.value} />
. What's the proper way to initialize it if I want to start off with a blank value? 0
is not equivalent to ''
, and anything I can think to pass in throws errors.
Is this an anti-pattern? I don't want to just hack a text input because I'd like to take advantage of built-in min / max / step functionality...
Passing ""
:
Warning: Failed prop type: Invalid prop value of type string supplied to NumInput, expected number.
Passing null
:
Warning: value prop on input should not be null. Consider using the empty string to clear the component or undefined for uncontrolled components.
Passing undefined
:
Warning: NumInput is changing an uncontrolled input of type number to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
An empty string is the correct value for an empty input, even if it's of type number
. You could add a guard inside <NumInput />
allowing you to pass in null
or undefined
or whatever you want from the rendering component, but pass in an empty string to the input
element when you determine the value to be empty.
// inside NumInput
const value = this.props.value;
const inputValue = !value && value !== 0 ? '' : value;
return <input type="number" value={inputValue} />
Also, I'm going to close this out since this is more of a usage question, and not really a bug or issue with React. We usually recommend using StackOverflow or some other platform for usage questions, as we try to use Github solely for issue tracking.
@Aweary - the bug is that React throws a warning when passing in an empty string to an input of type="number". If ""
is a proper value - then why the error?
Warning: Failed prop type: Invalid prop value of type string supplied to NumInput, expected number.
@jtulk That warning isn't coming from React's internal value validation, it's coming from your propTypes. Notice that the warning references NumInput
, not input
. You likely have something like:
propTypes = {
value: React.PropTypes.number,
}
@Aweary - Oh man! Sorry to waste your time. [slaps forehead]
Hey, just ran into the same problem and google did send me here instead of to stackoverflow ;) so for everyone who is ending up having the same issue...
NumberInput.propTypes = {
number: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
}
I hope i could help someone with this additional information with the same problem on number inputs.
I'm writing in TypeScript and my state variable is typed as undefined | number
by way of
interface muhState {
order?: number;
}
class muhForm extends Component(muhProps, muhState> {
public static defaultProps = {
order: undefined,
}
public state: muhState = {
order: this.props.order,
}
}
I still dislike setting order which is either undefined
or number
to ''
, but after reading the above, I seem to be vanish the warning by having the field in the form look like
<input type="number" value={orderId || ''} ..>
For all I know, by the time the TypeScript is turned into JavaScript what is happening is that order is being set to '', but at least as a one time mathematician, I don't have to know that!
Came here from Google with the exact same issue. I have an input that I want to be numbers only and I have my PropType set to a number. But of couse I don't want the input box initialized with a zero. I can't figure out a way around it, so I will have to switch my PropType to a string. Not a huge deal, but it'd be nice if there could be a way to enforce it to a number using my PropType and still make it work.
For anyone else who comes here wondering, I posted my question on Stack Overflow and got a good answer that worked for me. https://stackoverflow.com/questions/59793685/reactjs-number-only-input-with-proptype-set-to-number-but-gets-initialized-to
Most helpful comment
An empty string is the correct value for an empty input, even if it's of type
number
. You could add a guard inside<NumInput />
allowing you to pass innull
orundefined
or whatever you want from the rendering component, but pass in an empty string to theinput
element when you determine the value to be empty.