Cause constructor only run once when component was created, you need to update the state when `outerMsg` changed.
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
class Parent2 extends React.Component {
constructor(props) {
super(props);
this.state = {
msgFromOut: props.out,
};
}
getChildMsg = (data) => {
console.log("get the msg from child component data is ", data);
this.setState({
msgFromOut: 100 + data,
});
};
render() {
return (
<div className="parent">
this is father
<Child2 getMsg={this.getChildMsg} outerMsg={this.state.msgFromOut} />
<h1>{this.state.msgFromOut}</h1>
</div>
);
}
}
class Child2 extends React.Component {
constructor(props) {
super(props);
console.log("child is getting", props);
this.state = {
msgFromFather: props.outerMsg,
};
}
componentDidUpdate() {
if (this.state.msgFromFather !== this.props.outerMsg) {
this.setState({
msgFromFather: this.props.outerMsg,
});
}
}
handleClick = () => {
this.setState(
{
msgFromFather: this.state.msgFromFather + 3,
},
() => {
this.props.getMsg(this.state.msgFromFather);
}
);
};
// handleClick = () => this.props.getMsg(this.props.outerMsg + 3);
render() {
return <button onClick={this.handleClick}>to father</button>;
}
}
ReactDOM.render(<Parent2 out={1} />, document.querySelector("#root3"));
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root3"></div>
<!-- end snippet -->
Another way of triggering a child function from parent is to make use of the `componentDidUpdate` function in child Component. I pass a prop `triggerChildFunc` from Parent to Child, which initially is `null`. The value changes to a function when the button is clicked and Child notice that change in `componentDidUpdate` and calls its own internal function.
Since prop `triggerChildFunc` changes to a function, we also get a callback to the Parent. If Parent don't need to know when the function is called the value `triggerChildFunc` could for example change from `null` to `true` instead.
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
const { Component } = React;
const { render } = ReactDOM;
class Parent extends Component {
state = {
triggerFunc: null
}
render() {
return (
<div>
<Child triggerChildFunc={this.state.triggerFunc} />
<button onClick={() => {
this.setState({ triggerFunc: () => alert('Callback in parent')})
}}>Click
</button>
</div>
);
}
}
class Child extends Component {
componentDidUpdate(prevProps) {
if (this.props.triggerChildFunc !== prevProps.triggerChildFunc) {
this.onParentTrigger();
}
}
onParentTrigger() {
alert('parent triggered me');
// Let's call the passed variable from parent if it's a function
if (this.props.triggerChildFunc && {}.toString.call(this.props.triggerChildFunc) === '[object Function]') {
this.props.triggerChildFunc();
}
}
render() {
return (
<h1>Hello</h1>
);
}
}
render(
<Parent />,
document.getElementById('app')
);
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='app'></div>
<!-- end snippet -->
CodePen: https://codepen.io/calsal/pen/NWPxbJv?editors=1010