Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: Controlling input value with both props and state

Given a React component with a controlled input, I would like to be able to:

  1. Set the value of the input from the parent's state
  2. Allow the user to change the input to any value
  3. Update the parent's state only after the user submits and input passes validation.

I can accomplish 1 and 2 with the snippet below, but since the value came into the ChildComponent via props, I'm not sure how I can change the input value without changing the value of myInput on the parent.

class ChildComponent extends React.Component
{
    render(){
        return <input type="text" value={this.props.inputValue} onChange={this.handleChange.bind(this)} />
    }  
    handleChange(e){
        this.props.onInputChange(e.target.value);
    }
    handleSubmit(){
        // do some validation here, it it passes...
        this.props.handleSubmit();
    }
}

class ParentComponent extends React.Component{
    constructor(){
      super();
      this.state = {myInput: ""};
    }
    render(){
        return <ChildComponent inputValue={this.state.myInput} onInputChange={this.handleChange.bind(this)} />
    }
    handleChange(newValue){
        this.setState({myInput: newValue});
    }
    handleSubmit(){
        // do something on the server
    }
}
like image 697
Sean Avatar asked May 12 '15 03:05

Sean


2 Answers

Then you just need to move the state to the child component, instead of rendering from props.inputValue directly. Basically you'd just move handleChange to the child.

Set the initial value from props.inputValue in getInitialState, then make sure to update the child state in componentWillReceiveProps.

like image 56
Jomel Imperio Avatar answered Oct 12 '22 21:10

Jomel Imperio


componentWillReceiveProps is deprecated

Source: https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops

This lifecycle was previously named componentWillReceiveProps. That name will continue to work until version 17. Use the rename-unsafe-lifecycles codemod to automatically update your components.

Use something like this instead:

componentDidUpdate(prevProps) {       
        if (this.props.yourObj != null && prevProps.yourObj !== this.props.yourObj) {
            this.setState({
                yourStateObj = this.props.yourObj
            });
        }
}
like image 41
Tim Gerhard Avatar answered Oct 12 '22 19:10

Tim Gerhard