So I copied this function from a post here at stackoverflow, my goal was to be able to update a database and profile info right after the signup and before moving to a different route, the results are as I expect working however I can no longer access the state in the callback, can please someone assist me debug this code:
signup = (e) => {
this.setState({ loading: true });
e.preventDefault();
fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
.then((userCredentials) => {
if (userCredentials.user) {
userCredentials.user.updateProfile({
displayName: this.state.username,
photoURL: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdVmHPt9SajdsWlAZWzqRXkd-SzmmO9bBUV45fLnw5giijsty3OA',
}).then((s) => {
fire.database()
.ref(`master/${userCredentials.user.displayName}/setup/`)
.update({
bio: 'Be original',
})
.then(() => {
window.location.reload();
});
})
}
})
.catch(function (error) {
console.log(error);
this.setState({ signupError: true, loading: false, });
});
}
The error happen in catch(error)
TypeError: Cannot read property 'setState' of undefined
I suspect the issue comes from using multiple .then
JS functions has its own this
context.
In your case you use this
context inside a callback. this
context of the react component will be lost inside the callback. That is why catch block is unable to identify the setState
method
To preserve and use this
context inside the callback, assign this
to a local variable (named the variable as self in below example)
and access it inside the callback .
signup = (e) => {
var self= this;
this.setState({ loading: true });
e.preventDefault();
fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
.then((userCredentials) => {
if (userCredentials.user) {
userCredentials.user.updateProfile({
displayName: this.state.username,
photoURL: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQdVmHPt9SajdsWlAZWzqRXkd-SzmmO9bBUV45fLnw5giijsty3OA',
}).then((s) => {
fire.database()
.ref(`master/${userCredentials.user.displayName}/setup/`)
.update({
bio: 'Be original',
})
.then(() => {
window.location.reload();
});
})
}
})
.catch(function (error) {
console.log(error);
self.setState({ signupError: true, loading: false, });
});
}
You can also use arrow functions
, arrow functions
doesnot have its own this
context, so you'll be able to access this
context of the outerscope
.catch((error)=> {
console.log(error);
this.setState({ signupError: true, loading: false, });
});
this
in catch
is not your class, see different between normal function and arrow function. There're two way to solve your problem.
.catch(function (error) {
console.log(error);
this.setState({ signupError: true, loading: false, });
});
self
variable for this
signup = (e) => {
this.setState({ loading: true });
e.preventDefault();
const self = this; // It can be what ever you want, `self` is the most popular
...
}
then
.catch(function (error) {
console.log(error);
self.setState({ signupError: true, loading: false, });
});
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.