JackTheKnife
JackTheKnife

Reputation: 4154

ReactJS switching input element from controlled to uncontrolled with defined value state

Part of my code which fails looks like:

const normalizeInput = (value, previousValue) => {
    if (!value) return value;
    const currentValue = value.replace(/[^\d]/g, '');
    const cvLength = currentValue.length;

    if (!previousValue || value.length > previousValue.length) {
    if (cvLength < 4) return currentValue;
    if (cvLength < 7) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}`;
    return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3, 6)}-${currentValue.slice(6, 10)}`;
    }
    else {
       if (cvLength < 4) return currentValue;
       if (cvLength < 7) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}`;
    }
};


class Example extends Component {

constructor(props) {
    super(props);

    console.log(JSON.stringify(props))

    this.state = {
        editable: {},
        phoneNumber: '(123) 555-1234'
    }
}

handlePhoneChange(id, value) {
    this.setState(prevState=> ({ [id]: normalizeInput(value, prevState[id]) }));
};

render(){
    return(

        <input
        type="text"
        className="form-control react-form-input"
        id="phoneNumber"
        name="phoneNumber"
        value={this.state.phoneNumber}
        onChange={(e) => {this.handlePhoneChange('phoneNumber', e.target.value)}}
        />

    )}
}

It will complain as

A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled

on value={this.state.phoneNumber}

but when I will set it as value={this.state.phoneNumber || ''} will not but then on change will remove whole phoneNumber value instead on character.

Any tips on that?

Upvotes: 0

Views: 44

Answers (1)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 196197

This happens because your normalizeInput does not return anything when value.length <= previousValue.length (when you delete something)

So the undefined gets stored in your state and later given as value to your input, in effect making it uncontrolled.


The || '' fixes that because when your value is undefined you pass the '' empty string and so the input never receives an undefined value.

Upvotes: 1

Related Questions