简体   繁体   中英

React: Cannot read property 'setState' of undefined

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!

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); }); });

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);
      });
    });

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);
     });

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM