1
votes

I'm learning React and I created a really simple "shopping list app". Everything is working now but I'm getting this error: "Warning: A component is changing an uncontrolled input of type text 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".

Here it is my code:

function InputArea(props) {

    const [inputText, setInputText] = useState({
       inputText: {text: ""}
    });

    function handleChange(event){
        setInputText(event.target.value);
    }

    function handleClick(event) {
        props.onSubmit(inputText);
        setInputText({text: ""});
        event.preventDefault();
    }

    return(
             <div className="input-group w-50">
                <input 
                    type="text" 
                    className="form-control" 
                    onChange={handleChange} 
                    ariadescribedby="button-addon" 
                    value={inputText.text} 
                    placeholder="Insert Item">
                </input>
            <div className="input-group-append">
                <Button
                    id="button-addon"
                    color="dark"
                    style={{marginBottom: "2rem"}} 
                    onClick={handleClick}>Add Item
                </Button>
            </div>
        </div>
    )
}

The problem appears when I want to reset my input, in order to see the placeholder instead of the name of the last item added.

1

1 Answers

0
votes

The issue is in how you are updating state, how you use the state and how you initialise it.

With hooks unlike setState in classes, the values of state updater are not merged but replaced and when you run

setInputText({text: ""}); 

your inputText is replaced from its previous structure of

{
   inputText: {text: ""}
}

Causing you the error

Since you are using inputText.text to set value of input filed you must initialise the state also in that manner

const [inputText, setInputText] = useState({
   text: ""
}); // initialise as an object

function handleChange(event){
    setInputText({ text: event.target.value }); // update the state object with text field
}

function handleClick(event) {
    props.onSubmit(inputText);
    setInputText({text: ""});
    event.preventDefault();
}

return(
         <div className="input-group w-50">
            <input 
                type="text" 
                className="form-control" 
                onChange={handleChange} 
                ariadescribedby="button-addon" 
                value={inputText.text} 
                placeholder="Insert Item">
            </input>
        <div className="input-group-append">
            <Button
                id="button-addon"
                color="dark"
                style={{marginBottom: "2rem"}} 
                onClick={handleClick}>Add Item
            </Button>
        </div>
    </div>
)