Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clear uncontrolled field in react

I used to use ref for forms but now I always state for forms, I'm facing an issue where I have to clear a field after user submitted something.

handleSumbit = (e) => {
        e.preventDefault()
        const todoText = this.state.todoText
        if(todoText.length > 0){
            this.refs.todoTextElem = "" // wont work
            this.props.onAddTodo(todoText)
        } else {
            this.refs.todoTextElem.focus() //worked
        }
    }

    render() {
        return(
            <div>
                <form onSubmit={this.handleSumbit}>
                    <input ref="todoTextElem" type="text" onChange={e => this.setState({todoText: e.target.value})} name="todoText" placeholder="What do you need to do?" />
                    <button className="button expanded">Add Todo</button>
                </form>
            </div>
        )
    }

Clearing the ref simply don't work because it's a controlled input. I don't want to do something stupid like

passing a flag from parent component telling the form is submitted then use setState to clear the input. Or make onAddTodo to have a callback so that I can do

this.props.onAddTodo(todoText).then(()=>this.state({todoText:""}))
like image 853
Madeline Ries Avatar asked Jul 16 '17 06:07

Madeline Ries


1 Answers

The way you are using the input element is uncontrolled, because you are not using the value property, means not controlling it's value. Simply storing the value in state variable.


You don't need to store the input field value in state variable if you are using ref, ref will have the reference of DOM element, so you need to use this.refName.value to access the value of that element.

Steps:

1- Write the input element like this:

<input 
    ref= {el => this.todoTextElem = el} 
    type="text" 
    placeholder="What do you need to do?" />

To get it's value: this.todoTextElem.value

2- To clear the uncontrolled input field, clear it's value using ref:

this.todoTextElem.value = '';

Write it like this:

handleSumbit = (e) => {
    e.preventDefault()
    const todoText = this.todoTextElem.value;
    if(todoText.length > 0){

        this.todoTextElem.value = '';     //here

        this.props.onAddTodo(todoText)
    } else {
        this.todoTextElem.focus() 
    }
}

Another change is about the string refs, As per DOC:

If you worked with React before, you might be familiar with an older API where the ref attribute is a string, like "textInput", and the DOM node is accessed as this.refs.textInput. We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. If you're currently using this.refs.textInput to access refs, we recommend the callback pattern instead.

like image 54
Mayank Shukla Avatar answered Nov 01 '22 07:11

Mayank Shukla