You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React结合Firebase报错:Cannot read 'setState' of undefined

问题原因与解决方案

你遇到的Uncaught TypeError: Cannot read property 'setState' of undefined错误,核心原因是回调函数里的this指向不对——在then和forEach的普通function回调中,this并没有指向你的Dashboard组件实例,自然找不到setState方法。

另外,你的代码里还有几处小问题需要一起修正,下面一步步来解决:

1. 修复this指向问题

有三种常见方法可以解决这个问题,最推荐第一种(箭头函数),写法最简洁:

方法一:使用箭头函数替换普通function

箭头函数会自动继承外层作用域的this,也就是组件实例。修改你的componentDidMount方法:

componentDidMount() {
  const w = firebase.auth().currentUser;
  const rootRef = firebase.database().ref(`restaus/`).orderByKey();
  rootRef.once("value")
    // 这里改成箭头函数
    .then((snapshot) => {
      snapshot.forEach((childSnapshot) => {
        const key = childSnapshot.key;
        const childData = childSnapshot.val();
        // 现在this指向组件实例,可以正常调用setState了
        this.setState({ x: childData.pic });
      });
    });
  this.setState({ email: w.email });
}

方法二:提前保存this的引用

如果习惯用普通function,可以在回调前把组件的this存起来:

componentDidMount() {
  const w = firebase.auth().currentUser;
  const rootRef = firebase.database().ref(`restaus/`).orderByKey();
  // 保存组件的this引用
  const that = this;
  rootRef.once("value")
    .then(function (snapshot) {
      snapshot.forEach(function (childSnapshot) {
        const key = childSnapshot.key;
        const childData = childSnapshot.val();
        // 使用that代替this
        that.setState({ x: childData.pic });
      });
    });
  this.setState({ email: w.email });
}

2. 修正render里的错误

你在render里的几个引用需要调整:

  • <img src={this.x} /> 应该改成 <img src={this.state.x} />,因为x是存在组件的state里的,不是直接挂载在this上的属性。
  • <p className="product-price">{this.props.x}</p> 这里的this.props.x看起来是笔误,如果你要显示的是state里的x,应该改成{this.state.x}。

修正后的render部分:

render() {
  return (
    <div>
      <h4>your email is {this.state.email}</h4>
      <div className="product">
        <div className="product-image">
          {/* 改成this.state.x */}
          <img src={this.state.x} alt="product" /*onClick={this.quickView.bind(this, name)}*/ />
        </div>
        <h4 className="product-name">{this.state.x}</h4>
        {/* 这里如果是要显示state的x,就改成this.state.x */}
        <p className="product-price">{this.state.x}</p>
        <div className="product-action">
          <button type="button" >Add To cart</button>
        </div>
      </div>
    </div>)
}

额外提醒

注意你的forEach循环会遍历所有的childSnapshot,每次都会调用setState更新x,最终x会被最后一个childData.pic覆盖。如果你的需求是保存所有图片地址,应该把state里的x改成数组,比如:

// constructor里初始化x为数组
this.state = {
  speed: '',
  snapshot: undefined,
  x: []
}

// componentDidMount里的forEach部分
snapshot.forEach((childSnapshot) => {
  const childData = childSnapshot.val();
  // 把新的pic添加到数组里
  this.setState(prevState => ({
    x: [...prevState.x, childData.pic]
  }));
});

这样就能保存所有图片地址,后续在render里可以用map遍历渲染多个图片。

内容的提问来源于stack exchange,提问作者c newbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:24:43