How to create a controlled input with empty default in React 15

倖福魔咒の 提交于 2019-12-04 19:25:59


I'm having a problem with a text input that I want to be controlled, but it needs to support an empty value. Here is my component:

import React, { Component, PropTypes } from 'react';
import { ControlLabel, FormControl, FormGroup } from 'react-bootstrap';

const propTypes = {
  id: PropTypes.string.isRequired,
  label: PropTypes.string,
  onChange: PropTypes.func,
  upperCaseOnly: PropTypes.bool,
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

export default class UppercaseTextField extends Component {
  constructor(props) {
    this.state = { value: props.value };
    this.onChange = () => this.onChange();

  onChange(e) {
    let value =;
    if (this.props.upperCaseOnly) {
      value = value.toUpperCase();
    this.setState({ value });

  render() {
    return (
      <FormGroup controlId={id}>

UppercaseTextField.propTypes = propTypes;

When this is initially mounted, props.value is commonly (though not always) set to ''. This makes React 15 unhappy, as value='' makes the value get dropped, so React thinks it's an uncontrolled input, even though it has an onChange.

The component works, but I don't like getting this warning in the console:

Warning: FormControl is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info:

This worked fine in 0.14.x without any warnings, but now 15 seems to not like it. How do I clean it up to keep the functionality but get rid of the warning?


ensure this.state.value is not undefined on mount. You could do this in your constructor by setting this.state = {value: props.value || ''}; or by making props.value a required property.