Initializing React number input control with blank value?

I’d like my controlled input to initialize with no value in the box.
The input is a number, so I don’t pass in an empty ''.
Using defaultProps, I initialize the input with a null.

When typing into the input the console reports this message:

<MyInput> is changing an uncontrolled input of type number to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa).

To prevent this normally I initialize with an empty string to prevent this “switching” from happening. But with a number (I don’t want to show a 0, I want nothing to show) I am not sure how to do it.

static defaultProps = {
    estimatedHours: null,
    estimatedMinutes: null,
  }

defalut values ^^
<input
   type="number"
   onChange={(e) => this.handleChange('Hours', e.target.value)}
   onKeyDown={this.handleKeyDown}
   onPaste={this.handlePaste}
   value={estimatedHours}
   placeholder={hoursText}
   className="slds-input th-trailmix-textbox th-time-component__input"
/>

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Simpler approach is to have a fallback value be an empty string.
Works for type=number as well.

<input type="number" value={estimatedHours || ''} />

Method 2

You can set value Undefined,

Also add a check for input type if required

class Input extends React.Component {

    constructor(props) {
        super(props);
        this.state = {value: undefined};

        this.handleChange = this.handleChange.bind(this);
    }

    handleChange = (event) => {
        const isnum = /^d+$/.test(event.target.value);
        if (isnum) {
            return this.setState({
                value: Number(event.target.value),
            });
        }
    };

    render() {
        return (
            <input
                type="number"
                onChange={this.handleChange}
                value={String(this.state.value)}
                placeholder={"Please enter number"}
            />
        );
    }
}

and convert String to Number and vice versa

This won’t throw you an error for uncontrolled input

Method 3

I’d like my controlled input to initialize with no value in the box.

my problem is that I want a controlled number input with a null /
undefined initial value.

I suggest defaulting the value props in the input element with an empty string like the following:

<input
   type="number"
   // ...
   value={estimatedHours === undefined ? '' : estimatedHours}
/>

This will make the input empty and prevent the warning from React. It’ll also conveniently work well with the required prop too so the user must enter an input.

In TypeScript 3.7+, it can be shorted to the following using the nullish coalescing operator:

<input
   type="number"
   // ...
   value={estimatedHours ?? ''}
/>

Method 4

Uncontrolled inputs are simply inputs where you aren’t tying value to JavaScript. So if you are rendering:

<input value={any} />

That is a controlled input.

If you want to render an uncontrolled input with an empty value you could simply write

<input type="number" /> or <input type="number" placeholder="" />
or <input type="number" placeholder="please enter a number..." />

Next, if you want to pull the value use a ref.
state = {
  query: ''
}

handleSubmit = (e) => {
  e.preventDefault()
  this.setState({ query: this.search.value })
}

render() {
  return (
    <form>
      <input 
        type="number" 
        ref={input => this.search = input} 
        placeholder="" 
      />
      <button type="submit" onClick={this.handleSubmit}>Submit</button>
    </form>
  )
}

Additionally, you can still perform logic on the return value if you need to. ie:
handleSubmit = (e) => {
  e.preventDefault()
  this.setState({ query: this.search.value.toExponential(2) })
   // square whatever the user inputs and store in this.state.query
}

Method 5

The easiest way to get the behaviour you are looking for is to define the prop type for this field to a string. This will allow '' to be used as a default prop. On form submission, you will need to make sure that the value of this field is parsed to a number.

type FormProps = {
  estimatedHours: string;
  estimatedMinutes: string;
}

FormProps.defaultProps = {
  estimatedHours: '',
  estimatedMinutes: '',
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x