How come I am able to print my this.state.email after running componentDidMount() but when I pass the state to a child component I cannot access it in this.props.email of the child component
class HomePage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
isAuthorized: false,
name: "",
email: "",
};
}
loadGoogleApi() {
...
this.makeApiCall()
...
}
makeApiCall() {
gapi.client.people.people.get({
'resourceName': 'people/me',
'personFields': 'names,emailAddresses',
}).then(resp => {
this.setState({
name: resp.result.names[0].givenName,
email: resp.result.emailAddresses[0].value
});
});
}
componentDidMount() {
this.loadGoogleApi();
}
render() {
return(
<div>
{ !this.state.isAuthorized ? (
<button onClick={ this.handleAuthClick } id="authorize-button">Login/Signup</button>
) : (
<div>
<p>{ "Hello, " + this.state.name + "!" }</p>
<p>{ "Hello, " + this.state.email + "!" }</p>
<Main email={ this.state.email }/>
</div>
) }
</div>
);
}
}
Main.js component
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {};
console.log(this.props); // PRINTS ==> {email: ""}
}
render() {
return (
<div> Test </div>
);
}
}
export default Main;
In the first component initialization, it will take its props
. But later on if you set its props
like this.props = newProps
, this newProps
will be available in componentWillReceiveProps
. You can grab newProps
here and do whatever you want like assiging to state
.
In addition, you can refer here to have a look at React life cycle.
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.
Font: https://facebook.github.io/react/docs/react-component.html
React setState is an asynchronous function, sometimes they batch your state and put it on queue, in this case probably it's happening this:
Try to console.log the props inside componentWillReceiveProps
eg
componentWillReceiveProps(nextProps) {
console.log(nextProps);
}
Reason is constructor get called only once on initial rendering not after that, and you are logging the props
values in Child constructor so it will always print the initial props values if you want to see the updated value in Child put the console inside render it will print the updated value.
You can also use componentWillReceiveProps lifecycle method to check the udpated props values.
componentWillReceiveProps() is invoked before a mounted component receives new props.
Like this:
class Main extends React.Component {
render() {
//here
console.log(this.props);
return (
<div> Test </div>
);
}
}
The problem in your code is that , componentDidMount
is called after the first render Call in HomePage.js
. So the props are available in the child and since the constructor in the child is called only once, the props don't get updated. You need to make use of componentWillReceiveProps
and componentDidMount
in the child component if you want to update the state from props in the child or if you directly want to use it, use it in the render
PS Make sure to perform a undefined check in the child
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentWillReceiveProps(nextProps) {
console.log(nextProps);
}
render() {
console.log(this.props.email);
return (
<div> Test </div>
);
}
}
export default Main;
You can simply refresh state of your child component (Main.js) through componentWillReceiveProps method as follows.
class Main extends React.Component {
constructor(props) {
super(props);
this.state = { data: this.props.dataParentToChild }; // Initial data set
console.log(this.props); // PRINTS ==> {email: ""}
}
componentWillReceiveProps(nextProps) {
this.setState({ data: this.nextProps.dataParentToChild }); // Refresh data
console.log(this.nextProps); // PRINTS ==> {email: "updated value"}
}
render() {
return (
<div> Test </div>
);
}
}
export default Main;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.