状态更改后,如何使列表组件呈现?

时间:2019-05-24 07:58:59

标签: javascript reactjs firebase components lifecycle

我有一个计算器应用程序,可以记录任何用户通过Firebase实时处理的十个最新方程。它应该在任何时候任何设备上的某人命中等号时自动更新日志。除用户实际按下等号外,它在大多数情况下都会执行此操作,在这种情况下,它会延迟一个方程式。但是,该用户可以实时查看其他人的提交。

我有两个不同的状态变量。一个称为日志,它是一个对象,它从本地保存数据库中的所有日志,另一个称为列表,它是一个通过处理日志并按创建时间顺序获取十个最新条目的函数更新的数组。我有一个组件,该组件映射十个列表以在日志组件中创建li元素。

这是我的状态和componentDidMount方法:

this.state = {
      // input builds a string of user inputs
      input: '',
      // display is for the calculator screen
      display: '...',
      // stores all logs from db
      logs: {},
      // Make a list for 10 recent posts
      list: []
    }
}

  componentDidMount() {
    this.fetchData();
    document.addEventListener("keypress", this.handleKeyPress, true);
  }  

以下是适用于此问题的函数:

  // should fetch data (previous logs) for app on first render,
  // and also update logs live from user and other users
  fetchData = () => {
    // creating reference to root node of firebase db
    const rootRef = firebase.database().ref().child('/logs');
    // on "change" in db, pull all logs
    rootRef.on('value', snapshot => {
      this.setState({
        logs: snapshot.val()
      });
      return this.tenMostRecentLogs(this.state.logs)
    }, function (errorObject) {
      return console.log("The read failed: " + errorObject.code);
    })
  }

// take db object and update app state
  tenMostRecentLogs = obj => {
    // make array of all logs
    const logs = [
      Object.entries(obj)
    ];
    // create array of all logs sorted by timestamp
    const sortedLogs = logs[0].sort((a,b) => (a.timestamp < b.timestamp) ? 1 : -1)
    // create an array of ten most recent posted logs
    let tenLogsSorted = [];
    for (let i=0;i<10;i++) {
      let log = [];
      log.push(sortedLogs[i][1].eq);
      log.push(sortedLogs[i][1].id);
      tenLogsSorted.push(log)
    }
    this.setState({
      list: tenLogsSorted
    })
  }

这是有问题的组件:

<div className='log'>
  <Log logs={this.state.list}/>
</div>

我曾经考虑过要强制重新渲染Log,但是我知道那已经不合时宜了。有人看到我要去哪里了吗?

有问题的应用:https://calculatron-app.herokuapp.com/

3 个答案:

答案 0 :(得分:2)

this.setState()是异步操作。因此,在调用this.tenMostRecentLogs(this.state.logs)时,它无法在调用logs之后立即获得更新的this.setState({})值。要立即获取更新状态,您需要使用this.setState的回调函数。

例如: this.setState({logs:value,},()=>{ this.tenMostRecentLogs(this.state.logs) })

此外,this.tenMostRecentLogs()不会返回您编写的return this.tenMostRecentLogs(this.state.logs)的任何值。

请记住,对于函数,返回任何原始或非原始数据类型值。可能是函数,对象,数组或数字,字符串等...

答案 1 :(得分:1)

我将其作为一种更干净的方式来做您想做的事。

fetchData = () => {
  const rootRef = firebase.database().ref().child('/logs');

  rootRef.on('value',
    snapshot => this.tenMostRecentLogs(snapshot.val()),
    errorObject => console.log("The read failed: " + errorObject.code)
  );
}

tenMostRecentLogs = obj => {
  // the rest of your operation...

  this.setState({
    list: tenLogsSorted,
    logs: obj
  });
}

答案 2 :(得分:0)

return this.tenMostRecentLogs(snapshot.val())

在fetchData()内部而不是

return this.tenMostRecentLogs(this.state.logs)

谢谢@LadiAden !!!!