【问题标题】:React component not re-rendering to grab Firebase dataReact 组件不重新渲染以获取 Firebase 数据
【发布时间】:2017-04-19 07:05:10
【问题描述】:

下面的反应代码在第一次运行时从 Firebase 获取数据快照。 this.state.term 指的是我的 Firebase 数据库中节点的索引。我的handleChoice 函数执行this.setState,但它似乎没有重新渲染这个组件来获取新的数据快照。

this.state.term 的值在componentDidMount 下没有变化。但是,当我在渲染中控制台记录它时,它确实如此。

import React, { Component } from 'react';
import NavBar from './navbar.js';
import TermInfo from './termInfo.js';
import * as firebase from 'firebase';
import './App.css';

class App extends Component {

  constructor(){
    super();

    this.state = {
      term: 66,          //sample term to load first
      examples: [1,2,3],
      dataNode: {},
    }
  }

componentDidMount(){
      let rootRef = firebase.database().ref('vocab/').child(this.state.term);  

    rootRef.on('value', snap => {
        this.setState({ 
          dataNode: snap.val(),
          examples: Object.assign([], snap.val().examples)
        });
      });
  }


  _handleChoice(theChosenOne){
      this.setState({ 
        term: theChosenOne 
      });  
  }

  render() {
    console.log(this.state.term);   //this gives me the right index
    return (
      <div className="App">
        <div className="App-header">
        <NavBar choose={this._handleChoice.bind(this)}/>
        </div>
        <div className='container'>
        <div className="jumbotron"><TermInfo node={this.state.dataNode} examples={this.state.examples}/>
        <p className="App-intro">
          Enter a vocabulary term to search for and add examples! 
        </p></div>
      </div></div>
    );
  }
}

export default App;

为什么它不重新渲染并重新抓取数据?

【问题讨论】:

    标签: reactjs firebase firebase-realtime-database


    【解决方案1】:

    在状态更改 (_handleChoice) 后不会调用您的 componentDidMount,因此您不会在生成的 html 中看到更改。尝试在componentWillUpdate 中设置状态和与firebase 相关的配置,因为您希望它始终获得最新的this.state.term。见react's docs

    【讨论】:

      【解决方案2】:

      关键是componentDidMount 在 React 组件的生命周期中只会执行一次,并且会在初始渲染之后。再也不会了。

      引用official Doc:

      componentDidMount() 在组件运行后立即调用 安装。需要 DOM 节点的初始化应该放在这里。如果你 需要从远程端点加载数据,这是一个很好的地方 实例化网络请求。在此方法中设置状态将 触发重新渲染。


      似乎handleChoice 是基于某些事件(某些用户交互的结果)触发的。这意味着我们需要在每次调用 handleChoice 时调用 API。

      此外,我们不需要状态来维护所选索引。相反,让我们直接使用handleChoice 接收到的索引来获取 Firebase 快照。

      所以我们的组件看起来像:

      class App extends Component {
      
        constructor(){
          super();
      
          this.state = {
            examples: [1, 2, 3],
            dataNode: {},
          };
        }
      
        componentDidMount() {
          this.getData(66); // sample term to load first
        }
      
        getData(index) {
          const rootRef = firebase.database().ref('vocab/').child(index);
      
          rootRef.on('value', snap => {
            this.setState({ 
              dataNode: snap.val(),
              examples: Object.assign([], snap.val().examples)
            });
          });
        }
      
        _handleChoice(theChosenOne) {
          this.getData(theChosenOne);
        }
      
        render() {
          console.log(this.state.term);   //this gives me the right index
          return (
            <div className="App">
              <div className="App-header">
                <NavBar choose={this._handleChoice.bind(this)} />
              </div>
              <div className='container'>
                <div className="jumbotron">
                  <TermInfo node={this.state.dataNode} examples={this.state.examples}/>
                  <p className="App-intro">
                    Enter a vocabulary term to search for and add examples! 
                  </p>
                </div>
              </div>
            </div>
          );
        }
      }
      

      【讨论】:

      • 谢谢你教我mount和render的区别。我是个菜鸟。这就像一个魅力。
      猜你喜欢
      • 1970-01-01
      • 2016-03-05
      • 1970-01-01
      • 2021-04-28
      • 2022-01-27
      • 1970-01-01
      • 2023-03-13
      • 2021-06-19
      • 2018-04-22
      相关资源
      最近更新 更多