【问题标题】:ComponentDidMount returns undefined after initial mountComponentDidMount 在初始挂载后返回 undefined
【发布时间】:2019-01-16 02:23:49
【问题描述】:

我的组件在从 firebase 读取一次后正确安装,但在第二次尝试时失败,并说它无法获取值,因为“snap”未定义。我是新手,但我认为缺少绑定?

import React, { Component } from "react";
import "./solar.css";
import firebase from "firebase";
import { config } from "../config";

let app = firebase.initializeApp(config);
let database = app
  .database()
  .ref()
  .child("values")
  .child("Voltage");

class Solar extends Component {
  state = {
    voltage: 0
  };

  componentDidMount() {
    this.interval = setInterval(
      database.on("value", snap => {
        this.setState({
          voltage: snap.val()
        });
        console.log(snap.val());
      }),
      5000
    );
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

【问题讨论】:

  • 你为什么使用setInterval()
  • 我希望组件每隔 5 秒更新一次
  • 对 - 我已经提供了一个将setInterval 去掉的答案。要我重新插入吗?

标签: javascript reactjs firebase firebase-realtime-database


【解决方案1】:

您的setInterval 函数正在调用您为"value" 事件传递的事件处理程序。

发生这种情况是因为您传递给 onDatabase#on 方法 returns the callback(以便稍后在清理阶段取消注册该事件)。

因此,当setInterval 调用您的回调时,它将无法传入snap 参数,因为它会调用回调(而是database 实例) - 这解释了为什么snapundefined

另外 - 我不确定 setInterval 在这里的用途。当在数据库中检测到值更改时,您似乎只希望组件更新(重新渲染)。在这种情况下,调用setState() 就足够了。

考虑修改您的代码如下:

import React, {
  Component
} from "react";
import "./solar.css";
import firebase from "firebase";
import {
  config
} from "../config";

let app = firebase.initializeApp(config);
let database = app
  .database()
  .ref()
  .child("values")
  .child("Voltage");

class Solar extends Component {
  state = {
    voltage: 0
  };

  componentDidMount() {
  
    // Store reference to the "on value" callback for deregistering
    // the event when the Solar component unmounts
    this.valueChangeCallback = database.on("value", snap => {
      this.setState({
        voltage: snap.val()
      });
      console.log(snap.val());
    })
  }

  componentWillUnmount() {
  
    // If a valueChangeCallback exists from former mount then deregister
    // this callback from you database instance
    if(this.valueChangeCallback) {
      database.on("value", this.valueChangeCallback);
      this.deregisterCallback = '';
    }
  }
}

【讨论】:

  • 啊,谢谢。我已经回去修改了我的代码。这适用于此应用程序。我确实希望更新的速度比数据库更新的慢一点,但是有了这些信息,我能够正确地重新集成 setInterval,并且我知道如何正确设置它。
  • 不客气 - 很高兴我能帮上忙。听起来是个有趣的项目 :-)
猜你喜欢
  • 1970-01-01
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
  • 2019-01-04
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
相关资源
最近更新 更多