user7956921
user7956921

Reputation:

How to pass state as props so you can modify them

I have a main class here that holds three states rendering a Form component:

class MainApp extends React.Component{
 constructor(props){
   super(props);

   this.state = {
     fName: '',
     lName: '',
     email: ''
 }

render(){
  return(
     <div className="content">
          <Form formState={this.state}/>
     </div>
  )
}
}

And then inside my Form component I have ff codes:

class Form extends React.Component{
     constructor(props){
       super(props);

     }

    render(){
      return(
         <form>
            <input placeholder="First Name" value={this.props.formState.fName}
             onChange={e => this.setState({ this.props.formState.fName: e.target.value })}
         </form>
      )
    }
    }

Upon running this codes, I got an error saying it cannot read the property 'fName' of null.

How do I properly pass one state to it's children component so it can modify the main one?

Upvotes: 0

Views: 508

Answers (4)

Bastien
Bastien

Reputation: 158

I'm wondering why you want to pass a formState to the form itself. The form should manage is own state. It is not a good practice to do 2 way binding like the Form mutate the MainApp's state

However, if for some reasons you need a copy of you formState in your MainApp component, then your Form component should have an onSubmit callback method.

class MainApp extends React.Component{
  constructor(props){
    super(props);

    this.state = {
      form: null
    }
  }

  render() {
    return(
      <div className="content">
        <Form onSubmit={(form) => {
          this.setState({ form });
        })}/>
      </div>
    )
  }
}

class Form extends React.Component{
  constructor(props){
    super(props);

    this.state = {
      fName: '',
      lName: '',
      email: ''
    }
  }


  render(){
    return(
        <form onSubmit={e => this.props.onSubmit(this.state) }>
          <input placeholder="First Name" value={this.props.formState.fName}
            onChange={e => this.setState({ this.props.formState.fName: e.target.value })}
        </form>
    )
  }
}

Upvotes: 0

Prabhu
Prabhu

Reputation: 1057

        class MainApp extends React.Component{
         constructor(props){
           super(props);

           this.state = {
             fName: '',
             lName: '',
             email: ''
         }
          this._handleChange = this._handleChange.bind(this);
        }

     //dynamically update the state value using name 

      _handleChange(e) {
            const { name, value } = e.target;
            this.setState({
                [name]: value
            });
        }

        render(){
          return(
             <div className="content">
                //You can pass state and onchange function as params
                  <Form formState={this.state} _handleChange={this._handleChange}/>
             </div>
          )
        }
        }



   class Form extends React.Component{
        constructor(props){
          super(props);
       }

        render(){
           return(
            <form>
                <input placeholder="First Name"
                 defaultValue={this.props.formState.fName} 
                 id="fName"
                 name="fName"
                 onChange={e => this.props._handleChange} />
            </form>
         )
       }
     }

Upvotes: 1

Vadim Aidlin
Vadim Aidlin

Reputation: 326

You can't edit parent's state directly from child component. You should define handlers that would change parent's state in parent component itself, and pass them to children via props.

Parent:

class MainApp extends React.Component{
 constructor(props){
   super(props);
   this.state = {
     fName: '',
     lName: '',
     email: ''
   }

   fNameOnChange = (value) => {
     this.setState({fName:value})
   }

   render(){
     return(
       <div className="content">
         <Form formState={this.state} fNameChange={this.fNameOnChange}/>
       </div>
     )
  }
}

Child:

class Form extends React.Component{
 constructor(props){
   super(props);
 }

 render(){
   return(
      <form>
        <input placeholder="First Name" value={this.props.formState.fName}
        onChange={e => this.props.fNameChange(e.target.value))}
      </form>
    )
  }
}

Upvotes: 1

Rinkesh Golwala
Rinkesh Golwala

Reputation: 1039

You should pass a function as a prop to update the state of parent component. It is advised not to change props directly.

In your parent class write a function like:

onChangeHandler (data) {
  this.setState({fname: data})
}

And pass it to the child component and you can call this method as this.props.onChangeHandler(event.target.data) from child component.

Thanks

Upvotes: 0

Related Questions