реагирующие переменные не отображаются в рендере, но после перезагрузки происходит что-то не так - PullRequest
0 голосов
/ 02 апреля 2020

oke Я написал следующий класс:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';

import moment from 'moment';

import * as ROUTES from '../../constants/routes';

export class ReservationListBase extends Component {
     constructor(props){
          super(props)

          this.state = {
          ...props,
          ReservationList: null,
          loading: true,
          }
      }

  componentDidMount(){
  this.props.firebase
    .reserveringen()
    .orderByChild("futureReservation")
    .equalTo(true)
    .on('value', snapshot => {

        const ReservationObject = snapshot.val()

        if(ReservationObject !== null){
          let ReservationList = Object.keys(ReservationObject).map(key => ({
              ...ReservationObject[key],
              uid: key,
          }))

          ReservationList.map((reservation, index) => {
            this.props.firebase
              .boot(reservation.bootuid)
              .on('value' , snapshot => {
                  ReservationList[index]['bootnaam'] = snapshot.val().bootnaam
                  ReservationList[index]['boottype'] = snapshot.val().boottype
              })

            this.props.firebase
              .user(reservation.useruid)
              .on('value', snapshot => {
                ReservationList[index]['username'] = snapshot.val().username
              })
          })
          console.log("after filling data")
          console.log(ReservationList)

          ReservationList = this.checkIfNotFuture(ReservationList)

          this.setState({
            ReservationList,
            loading: false,
          })

          return ReservationList
        } else {
          this.setState({
            ReservationList: [],
            loading: false,
          })

          return []
        }
      })
}

checkIfNotFuture(ReservationList){
     const now = moment()

     ReservationList.map((reservation, index) => {
           const endDate = moment(reservation.endDate)

           if(now > endDate){
                this.props.firebase
                    .reservering(reservation.uid)
                    .update({
                         futureReservation: false,
                    })

                ReservationList.splice(index, 1)
          }})

     return ReservationList
 }

 componentWillUnmount(){
      this.props.firebase
          .reserveringen()
          .orderByChild("futureReservation")
          .equalTo(true)
          .off()

      this.setState({
           ReservationList: null
      })
}

render() {
const {ReservationList, loading} = this.state

console.log("state in render")
console.log(ReservationList)

return (
  <div>
    {ReservationList &&
      <ul>
        {ReservationList.map(reservation => (
          <li key={reservation.uid}>
            <span>
              <strong>start reservering</strong> {reservation.startDate}
            </span>
            <span>
              <strong>einde reservering</strong> {reservation.endDate}
            </span>
            <span>
              <strong>bootnaam</strong> {reservation.bootnaam}
            </span>
            <span>
              <strong>boottype</strong> { reservation.boottype }
            </span>
            <span>
              <strong>gebruiker</strong> { reservation.username }
            </span>
          </li>
        ))}
      </ul> 
    }
    {!loading &&
    <div>
      {!ReservationList &&
        <div>
          geen reserveringen aanwezig
        </div>
      }
    </div>  
    }

    <Link to={ROUTES.RESERVERINGEN_DATETIME}>Maak Nieuwe Reservering</Link>

  </div>
)
}
}

export default ReservationListBase

Я знаю, что это много, но я не знаю, где возникает проблема, (также извините за некоторые голландские имена в переменных). без ошибок, только просмотр предупреждений об отсутствии операторов возврата из функций стрелок

основная проблема заключается в том, что переменные «booking.bootnaam» и «servation.boottype »(их можно найти в рендере, не отображаются когда список загружается в первый раз, после перезагрузки они делают, но, конечно, мне нужно, чтобы они показывали в первый раз

этот класс имеет возможность без проблем связываться с firebase

дополнительная информация :

журнал консоли выглядит следующим образом:

[{…}]
0:
    bootuid: "-M2iYgSUHJrEEE1C5GSB"
    endDate: "2020-04-02T21:15:00+02:00"
    futureReservation: true
    startDate: "2020-04-02T20:45:00+02:00"
    useruid: "JXPeUeF5NzgatXriREpdwcTa71W2"
    uid: "-M3ue2p3I0B-WYz5-g-p"
    username: "Harry Janssen"
    bootnaam: "aquilo"
    boottype: "4+"
    __proto__: Object
    length: 1
    __proto__: Array(0)
ReservationListBase.js:124 state in render
ReservationListBase.js:125 
[{…}]
    0:
    bootuid: "-M2iYgSUHJrEEE1C5GSB"
    endDate: "2020-04-02T21:15:00+02:00"
    futureReservation: true
    startDate: "2020-04-02T20:45:00+02:00"
    useruid: "JXPeUeF5NzgatXriREpdwcTa71W2"
    uid: "-M3ue2p3I0B-WYz5-g-p"
    username: "Harry Janssen"
    bootnaam: "aquilo"
    boottype: "4+"
    __proto__: Object
    length: 1
    __proto__: Array(0)
ReservationListBase.js:124 state in render
ReservationListBase.js:125 
[{…}]
    0:
    bootuid: "-M2iYgSUHJrEEE1C5GSB"
    endDate: "2020-04-02T21:15:00+02:00"
    futureReservation: true
    startDate: "2020-04-02T20:45:00+02:00"
    useruid: "JXPeUeF5NzgatXriREpdwcTa71W2"
    uid: "-M3ue2p3I0B-WYz5-g-p"
    username: "Ronne Timmerman"
    bootnaam: "aquilo"
    boottype: "4+"
    __proto__: Object
    length: 1
    __proto__: Array(0)

, поэтому из get go видно, что «bootnaam» и «boottype» доступны из состояния

1 Ответ

0 голосов
/ 02 апреля 2020

Похоже, у вас есть несколько методов, которые асинхронно загружают данные из Firebase. В этом случае вам необходимо обновить состояние в каждом из этих методов или в последнем методе, завершающем загрузку. Теперь вы устанавливаете состояние только в самом внешнем методе загрузки, что означает, что вы устанавливаете состояние до загрузки bootnaam, boottype и username.

console.log() это приводит вас на неверный путь, поскольку консоль Chrome JavaScript фактически обновляет объект при загрузке дополнительных данных. Часто это то, что вы хотите, но здесь это затрудняет поиск и устранение неисправностей. Чтобы увидеть объект таким, какой он есть, когда вы регистрируете его, вы можете попробовать:

  console.log("after filling data")
  console.log(JSON.stringify(JSON.parse(ReservationList)))

Это гарантирует, что вы напечатаете снимок stati c JSON во время оператора console.log .

Как уже говорилось, для решения проблемы вам нужно вызвать setState во вложенных обработчиках on('value'. Вы можете:

  • либо вызывать setState всякий раз, когда загружаются какие-либо данные, что означает, что вы создаете состояние компонента, когда оно поступает из базы данных.
  • или звоните setState только тогда, когда вы знаете, что все данные доступны. Это означает, что вам нужно сохранить некоторое внутреннее состояние в компоненте для отслеживания этого.

Поскольку первое проще, я рекомендую пойти по этому пути. Это означает, что ваш код рендеринга должен быть в состоянии справиться с отсутствием свойств, которые загружаются асинхронно, но в целом это хорошая практика. Кроме того, код будет выглядеть примерно так:

  ReservationList.map((reservation, index) => {
    this.props.firebase
      .boot(reservation.bootuid)
      .on('value' , snapshot => {
          ReservationList[index]['bootnaam'] = snapshot.val().bootnaam
          ReservationList[index]['boottype'] = snapshot.val().boottype
          this.setState({
            ReservationList
          })
      })

    this.props.firebase
      .user(reservation.useruid)
      .on('value', snapshot => {
        ReservationList[index]['username'] = snapshot.val().username
        this.setState({
          ReservationList
        })
      })
...