“反应已检测到钩子顺序的变化”,但顺序似乎已保留

时间:2019-09-13 15:54:38

标签: reactjs react-hooks

   Previous render            Next render
   ------------------------------------------------------
1. useState                   useState
2. useContext                 useContext
3. useEffect                  useEffect
4. undefined                  useState
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    in ExperienceDetailContainer (created by ConnectFunction)
    in ConnectFunction (created by Route)
    in Route (created by withRouter(Connect(ExperienceDetailContainer)))
    in withRouter(Connect(ExperienceDetailContainer)) (created by ExperiencePage)

在使用钩子获得意外错误。据我了解,只要以可预测的顺序调用钩子,一切都应该正常工作。仔细查看我的组件,便可以看出是这种情况,而且我无法理解错误的出处。

import React, { useState, useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import T from 'prop-types'
import { useWait } from 'react-wait'
import { connect } from 'react-redux'
import api from 'services/api'
import {
  formattedDateWithoutTime,
  getTimesForCurrentDate
} from 'utils/helpers'
import { fromResource, fromUserSelections, fromSocial } from 'store/selectors'
import {
  resourceDetailReadRequest,
  changeExperienceDate,
  changeExperienceTime,
  updateExperience,
} from 'store/actions'
import { ExperienceDetail, Spinner } from 'components'

const ExperienceDetailContainer = ({
  detail,
  readDetail,
  experienceDate,
  changeExperienceDate,
  experienceTime,
  changeExperienceTime,
  adults,
  kids,
  updateExperience,
  user,
  ...props
}) => {
  const [error, setError] = useState('')
  const { startWaiting, endWaiting } = useWait()

  useEffect(() => {
    readDetail(apiRequestParams)
    getExperienceAvailabilities()
  }, [])

  const experienceId = props.match.params.experienceid
  const cityId = props.match.params.cityid

  const apiRequestParams = {
    endpoint: "GetExperienceInfo",
    experienceid: experienceId,
    adults,
    kids
  }

  const availableStartTimes = getTimesForCurrentDate(experienceDate, detail.availabilities)

  const getExperienceAvailabilities = () => {
    api.post('/GetExperienceAvailabilities', {
      experienceid: experienceId
    })
    .then(result => {
      const availabilities = result.d
      updateExperience(availabilities)
    })
    .catch(err => {
      console.error(err)
    })
  }

  if (!detail.experienceid) {
    return <Spinner />
  }

  return <ExperienceDetail
    loading={!detail.experienceid}
    {...{
      detail,
      error,
      experienceId,
      availableStartTimes,
      changeExperienceDate,
      experienceDate,
      changeExperienceTime,
      experienceTime,
      getQuoteBooking,
  }}/>
}

ExperienceDetailContainer.propTypes = {
  detail: T.object.isRequired,
  changeExperienceDate: T.func.isRequired,
  experienceDate: T.instanceOf(Date),
  changeExperienceTime: T.func.isRequired,
  experienceTime: T.string,
  adults: T.number.isRequired,
  kids: T.number.isRequired,
}

const mapStateToProps = state => ({
  user: fromSocial.getUser(state),
  detail: fromResource.getDetail(state, 'experience'),
  experienceDate: fromUserSelections.getDate(state),
  experienceTime: fromUserSelections.getTime(state),
  adults: fromUserSelections.getAdults(state),
  kids: fromUserSelections.getAdults(state),
})

const mapDispatchToProps = (dispatch) => ({
  readDetail: (apiRequestParams) => dispatch(resourceDetailReadRequest('experience', { apiRequestParams })),
  changeExperienceDate: (experienceDate) => dispatch(changeExperienceDate(experienceDate)),
  changeExperienceTime: (experienceTime) => dispatch(changeExperienceTime(experienceTime)),
  updateExperience: (availabilities) => dispatch(updateExperience('experience', availabilities))
})

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(ExperienceDetailContainer))

可以看出,我正在使用3个钩子:useState,useWait,useEffect。它们全都在顶层被调用,而不是有条件的或任何会破坏顺序的东西。

我在这里有一些基本误会吗?

0 个答案:

没有答案