1

I want to call child function from parent component so I found a question here

Call child method from parent

So I used this way to to called it (From 1st Answer and 2nd approach).

Now issue is how to set state in the child getAlert function

class Parent extends Component {
  render() {
    return (
      <div>
        <Child ref={instance => { this.child = instance; }} />
        <button onClick={() => { this.child.getAlert(); }}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  constructor(){
     super();
     this.state = {message:""};
  }

  getAlert() {
    alert('clicked');
    //HERE I NEED TO SETSTATE 
  }

  render() {
    return (
      {this.state.message!=""?(
         <h1>{this.state.message}</h1>

      ):(

      <h1>Hello</h1>

      )}
    );
  }
}

In the getAlert function of child I need to setState but I couldn't able to do it. Please provide any solution

Kushal Jain
  • 3,029
  • 5
  • 31
  • 48

2 Answers2

1

class Parent extends React.Component {
  render() {
    return (
      <div>
        <Child ref={instance => { this.child = instance; }} />
        <button onClick={() => { this.child.getAlert(); }}>Click</button>
      </div>
    );
  }
}

class Child extends React.Component {
  constructor(){
  super()
  this.state = {
    message: 'google'
  }
  this.getAlert = this.getAlert.bind(this)
  }
    
  getAlert() {
    alert('clicked');
    this.setState ({
      message: 'yahoo'
    }, () => {
      console.log(this.state.message) //the state value will be printed
    }); 
  }

  render() {
  console.log(this.state.message)
    return (
      <h1>Hello {this.state.message}</h1>
    );
  }
}

ReactDOM.render(
  <Parent />,
  document.getElementById('container')
);
<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="container"></div>

you have bind the getAlert() method to scope of the class ie). 'this'. I have added an sample code..pls check

Jayabalaji J
  • 1,016
  • 7
  • 9
  • No error, I just did that you wrote. I put these line inside getAlert function this.setState({message:"Yahoo"}); console.log(this.state.message); so console.log always print blank – Kushal Jain Nov 16 '17 at 08:47
  • try using console.log() inside callback of setState function or inside render() method. Because setState behaves asynchronously so the new state will not be available if u log it immediately – Jayabalaji J Nov 16 '17 at 08:49
  • console.log is not my concern. My concern is about state update if state is not updating then render of child component doesn't work. Please look at the edited question then you will understand state use – Kushal Jain Nov 16 '17 at 08:54
  • I have added a working fiddle for the same..pls check – Jayabalaji J Nov 16 '17 at 09:02
1

The problem seems to be that when calling setState inside the getAlert function of child, this.setState will come undefined. This happens because this inside your getAlert function doesn't refer to the context of the React Component and setState is defined for the Component. You can solve this by binding the getAlert function.

You can do it in two ways.

First: using .bind(this) in constructor

class Child extends Component {

  constructor() {
     super();
     this.getAlert = this.getAlert.bind(this);
  }
  getAlert() {
    alert('clicked');
    //HERE I NEED TO SETSTATE 
  }

  render() {
    return (
      <h1>Hello</h1>
    );
  }
}

Second: use Arrow function

getAlert = ()  => {
    alert('clicked');
    //HERE I NEED TO SETSTATE 
  }

Check this answer on Why do we need to bind React functions

Check the working snippet

class Parent extends React.Component {
  render() {
    return (
      <div>
        <Child ref={instance => { this.child = instance; }} />
        <button onClick={() => { this.child.getAlert(); }}>Click</button>
      </div>
    );
  }
}

class Child extends React.Component {
  constructor(){
     super();
     this.state = {message:""};
  }

  getAlert = () => {
    alert('clicked');
    this.setState({message: "somemessage"});
  }

  render() {
    return (
      <div>{this.state.message!=""?(
         <h1>{this.state.message}</h1>

      ):(

      <h1>Hello</h1>

      )}</div>
    );
  }
}

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"/>
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • What error do you get, can you elaborate your problem – Shubham Khatri Nov 16 '17 at 08:42
  • No error, I just did that you wrote. I put these line inside getAlert function this.setState({message:"Yahoo"}); console.log(this.state.message); so console.log always print blank – Kushal Jain Nov 16 '17 at 08:46
  • In that case you need to see this https://stackoverflow.com/questions/41278385/updated-state-not-reflecting-after-setstate/41278440#41278440 – Shubham Khatri Nov 16 '17 at 08:47
  • console.log is not my concern. My concern is about state update if state is not updating then render of child component doesn't work. Please look at the edited question then you will understand state use – Kushal Jain Nov 16 '17 at 08:54
  • Thanks, may be there is some other issue in my code need to look again. – Kushal Jain Nov 16 '17 at 09:08