Reputation: 509
I've got some data from Firebase Realtime Database and now I'm trying to add it to a variable. I'm sure that the querying works, because if I console.log(dataSnapshot) it logs the correct data (which is 001). However, when I'm trying to create a variable out of that number I get the following error: Cannot read property 'setState' of undefined and it doesn't return anything to the console.
Here's my code:
class Table extends Component {
constructor(props) {
super(props);
this.state = { timestamps: [], user: auth().currentUser, serial: "" };
}
componentDidMount() {
const uid = this.state.user.uid;
console.log(uid);
let serial = this.state.serial;
const serialRef = db.ref(uid + "/serial");
serialRef.once("value").then(function (dataSnapshot) {
console.log(dataSnapshot.val());
this.setState({ serial: dataSnapshot.val() }, () => {
serial = this.state.serial;
console.log(serial);
});
});
Here's the screenshot of my console
Thanks in advance!
Upvotes: 0
Views: 89
Reputation: 312
you are not using arrow callback function, If you don't use arrow callback you have to bind you function. If you don't want to write bind statement use arrow function which will get the context of the class automatically.
serialRef.once("value").then((dataSnapshot) => {
console.log(dataSnapshot.val());
this.setState({ serial: dataSnapshot.val() }, () => {
serial = this.state.serial;
console.log(serial);
});
});
Upvotes: 1
Reputation: 280
the arrow function should retain your this context
serialRef.once("value").then((dataSnapshot) => {
console.log(dataSnapshot.val());
this.setState({ serial: dataSnapshot.val() }, () => {
serial = this.state.serial;
console.log(serial);
});
Upvotes: 0
Reputation: 32067
Your problem is that the callback you pass to serialRef.once("value").then(...)
does not have a "this" context set. If you change your code to this, it should work:
componentDidMount() {
const uid = this.state.user.uid;
console.log(uid);
let serial = this.state.serial;
const serialRef = db.ref(uid + "/serial");
// grab a reference to the current "this" context
const table = this;
serialRef.once("value").then(function (dataSnapshot) {
console.log(dataSnapshot.val());
// invoke setState on the captured context
table.setState({ serial: dataSnapshot.val() }, () => {
serial = table.state.serial;
console.log(serial);
});
});
Or you could use a lambda function, like you already do in the setState call:
componentDidMount() {
const uid = this.state.user.uid;
console.log(uid);
let serial = this.state.serial;
const serialRef = db.ref(uid + "/serial");
// "Fat arrow" or "lambda" functions implicitly capture the current "this" context
serialRef.once("value").then((dataSnapshot) => {
console.log(dataSnapshot.val());
this.setState({ serial: dataSnapshot.val() }, () => {
serial = this.state.serial;
console.log(serial);
});
});
Upvotes: 0