Anh Tuan Nguyen Anh Tuan Nguyen - 1 month ago 25
React JSX Question

reactjs parent trigger child component

I have a parent component, which is basically a Form.

export default class Parent extends Component{
submitInput(event){
...call Children
}

render(){
return(
<div>
<form className="form-horizontal" onSubmit= {this.submitInput.bind(this)}>
{this.props.children}
<button type="submit">Submit</button>
</div>
</form>
</div>);
}}


The children can be different types of inputs all with a common function called validate().

Here is one example of a child

export default class Child extends Component{

validate(){
..validate stuff
}


render(){
return(
<div className="form-group">
<textarea ref={this.props.name} />
</div>
);
}
}


On Submission of the parent Component I want validate all Child inputs using their validate() function.

How can I do that?

Thanks in advance

Answer

Clone the entire children with new ref prop using React.cloneElement. On submit use the refs to access the child's methods.

See the example below. If more elaboration needed, please comment.

Hope this helps!

class Form extends React.Component{
  submitInput(){
    this.childrenClone.forEach((el) => {
      var r = el.ref //use the ref to access the child's methods
      this.refs[r].validate()
    })
  }
  
  render() {
    this.childrenClone = React.Children.map(this.props.children,
     (child) => React.cloneElement(child, {
       ref: Math.random().toString(36).slice(-5) //add a random string as a ref
     })
    )
    
    return <div>
      <form className="form-horizontal"  onSubmit={this.submitInput.bind(this)}>
       {this.childrenClone}
       <button type="submit">Submit</button>
       </form>
    </div>
  }
}


class Child extends React.Component{
  validate(){
    console.log('validate textarea') //on validate log this
  }
  
  render() {
    return <div className="form-group">
          <textarea />
      </div>
  }
}

class ChildInput extends React.Component{
  validate(){
    console.log('validate Input') //on validate log this
  }
  
  render() {
    return <div className="form-group">
          <input type="text" />
      </div>
  }
}
class Parent extends React.Component{
  render(){
    return <Form>
      <Child/>
      <Child/>
      <ChildInput/>
      <ChildInput/>
    </Form>
  }
}

ReactDOM.render(<Parent/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>