1

I have an input field in React.

<input 
    type = "number"
    value = {this.props.answer || undefined}
    onKeyUp = {(e) => (e.keyCode === 13) ? onAnswer(e.target.value) : false }
/>

This way it behaves just like I need it to behave:

  • If there is no this.props.answer there is no inital value in the input.
  • User can input any number. Nothing happens on onChange
  • Once user presses Enter, the state changes (in the onAnswer function). After this, the value of the input field stays this.props.answer and the user can NOT change the value any more.

But when the user presses Enter I get this warning:

A component is changing an uncontrolled input of type number to be controlled.

I read about uncontrolled components and I tried this:

<input 
    type = "number"
    defaultValue = {this.props.answer || undefined}
    ref={this.input}
    onKeyUp = {(e) => (e.keyCode === 13) ? onAnswer(e.target.value) : false }
/>

This way I doesn't get the warning but the input field remains editable after the user presses Enter. I also tried using both value and defaultValue properties but then again I get the same warning.

I want the input field to be sort of controlled but I don't want to change the state on onChange but only when user presses Enter (onKeyUp). After this, the user should not be able to edit the input. Is there a way to implement this behavior?

UPDATE: I wasn't aware that I can set the readOnly property of the input based on the state. Setting it to false after setting the state solves my problem.

  • If you don't want the user to be able to edit the value, then shouldn't you toggle the `disabled` or `readonly` state instead? – rickdenhaan Apr 22 '20 at 14:55
  • It is unclear what you are trying to do. Can you take a step back and explain? Do you want to make the form read-only once submitted? – Davin Tryon Apr 22 '20 at 14:55
  • @rickdenhaan I didn't know about `readonly`. It just solve my problem. Thanks! – Daniel Tahin Apr 22 '20 at 15:02
  • 1
    @DavinTryon It's not really a form just an input field but yes, I need to make it read only after user presses Enter and the state changes. But setting the `readonly` property solved my issue. – Daniel Tahin Apr 22 '20 at 15:04

1 Answers1

0

You can prevent the input from being edited in the keyUp event handler:

onKeyUp = (e) => {
   // Check if we still accept typing
   if (no_more_typing) return e.preventDefault();
   // Handle enter key
   if (e.keyCode === 13) onAnswer(e.target.value);
}

<input
  onKeyUp={onKeyUp} ...
HermitCrab
  • 3,194
  • 1
  • 11
  • 10
  • Excuse me if I'm missing something but this isn't working for me. Initially I can enter some numbers and nothing happens until I press Enter key. Then the state is set -> it's OK until this moment but after I can still edit the input value. The code goes into the first `if` branch but it seems like `e.preventDefault()` does not prevent me from editing the value of the input field. UPDATE: your solution works if I use `value` instead of `defaultValue` on the input but then it causes the same warning: `A component is changing an uncontrolled input of type number to be controlled.` – Daniel Tahin Apr 22 '20 at 15:28
  • Could you try with `onKeyPress` instead of `onKeyUp`, this is what I use to filter out some characters that I don't want and it works – HermitCrab Apr 22 '20 at 15:32
  • Regarding the warning, when you do `value=undefined`, it means that your input is uncontrolled (basically input is self managing its value). But then when you do `value={this.props.answer}`, then your input becomes controlled because you're imposing a value. Could you try `value = {this.props.answer || ''}` – HermitCrab Apr 22 '20 at 15:39
  • `onKeyPress` does not work. There is no `e.keyCode`. – Daniel Tahin Apr 22 '20 at 16:47
  • If I use `value = {this.props.answer || ''}` this is the warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`. – Daniel Tahin Apr 22 '20 at 16:47
  • with `onKeyPress` you can do: `if (event.key === 'Enter')` – HermitCrab Apr 22 '20 at 16:48
  • If you set the value, then you must also have an onChange event handler, that's the way it is – HermitCrab Apr 22 '20 at 16:49