【问题标题】:React: Cannot read property 'setState' of undefined反应:无法读取未定义的属性“setState”
【发布时间】:2020-08-18 13:43:09
【问题描述】:

我从 Firebase 实时数据库中获得了一些数据,现在我正在尝试将其添加到变量中。我确信查询有效,因为如果我 console.log(dataSnapshot) 它记录正确的数据(即 001)。但是,当我尝试使用该数字创建变量时,出现以下错误:Cannot read property 'setState' of undefined 并且它不会向控制台返回任何内容。

这是我的代码:

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

提前致谢!

【问题讨论】:

标签: javascript reactjs setstate


【解决方案1】:

你没有使用箭头回调函数,如果你不使用箭头回调你必须绑定你的函数。如果您不想编写绑定语句,请使用箭头函数,它会自动获取类的上下文。

serialRef.once("value").then((dataSnapshot) => {
      console.log(dataSnapshot.val());
      this.setState({ serial: dataSnapshot.val() }, () => {
        serial = this.state.serial;
        console.log(serial);
      });
    });

【讨论】:

    【解决方案2】:

    您的问题是您传递给serialRef.once("value").then(...) 的回调没有设置"this" context。如果您将代码更改为此,它应该可以工作:

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

    或者你可以使用一个 lambda 函数,就像你已经在 setState 调用中所做的那样

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

    【讨论】:

    • 感谢您的回答!这现在有效。但是,如果我想在该函数之外执行 console.log(serial),它不会记录任何内容。 serialRef.once("value").then((dataSnapshot) => { console.log(dataSnapshot.val()); this.setState({ serial: dataSnapshot.val() }, () => { serial = this.state.serial; console.log(serial); }); }); console.log(this.state.serial);您对我如何在代码中进一步使用该变量有任何建议吗?
    • 我假设您指的是此评论中的最后一个 console.log?在这种情况下,我很确定这是因为 serialRef.once() 和 this.setState() 本质上都是 asynchronous 的。实际上,这意味着您的代码执行到达最后一个 console.log() setState 完成之前,因此您试图在设置值之前记录它。如果你想确保在做某事之前设置状态,你应该在 setState 的回调中做,就像你原来的例子一样。
    【解决方案3】:

    箭头函数应该保留你的 this 上下文

    serialRef.once("value").then((dataSnapshot) => {
         console.log(dataSnapshot.val());
         this.setState({ serial: dataSnapshot.val() }, () => {
           serial = this.state.serial;
           console.log(serial);
         });
    

    【讨论】:

      猜你喜欢
      • 2020-09-07
      • 2017-01-01
      • 2018-10-06
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 2019-04-09
      • 2019-12-30
      • 2017-05-30
      相关资源
      最近更新 更多