简体   繁体   English

突变更新阿波罗缓存,但缓存更新未反映在 UI 中

[英]Mutation updates apollo cache but cache update not reflected in UI

I'm using Apollo Client with React, I've outlined my Query / Mutation usage in the MWE below.我在 React 中使用 Apollo Client,我在下面的 MWE 中概述了我的Query / Mutation用法。

I have a Query which fetches a user's appointments:我有一个Query来获取用户的约会:

const GET_USER_APPOINTMENTS = gql`
  query getUserAppointments {
    getUserAppointments {
      id
      appointmentStart
      appointmentEnd
      appointmentType
      status
    }
  }
`
// omitted code for brevity...

<Query query={GET_USER_APPOINTMENTS} fetchPolicy='network-only'>
  {({ loading, error, data }) => {
    if (loading) return <div>Loading...</div>
    if (error) return `Error ${error}`

    const appointments = data.getUserAppointments

    return <BookingsBlock appointments={appointments} />
  }}
</Query>

The BookingsBlock is represented by this MWE: BookingsBlock由这个 MWE 表示:

export default class BookingsBlock extends Component {
  constructor (props) {
    super(props)
    let pastAppointments = []
    let futureAppointments = []
    if (props.appointments) {
      // assign past and future appointments
      props.appointments.forEach(appt => {
        if (moment(appt.appointmentStart) < moment()) {
          pastAppointments.push(appt)
        } else {
          futureAppointments.push(appt)
        }
      })
    }
    this.state = { pastAppointments, futureAppointments }
  }

  render () {
    let pastAppointmentsBlock
    let futureAppointmentsBlock

    const EmptyBlock = (
      <EmptyBookingBlock>
        <h3>You have no appointments!</h3>
      </EmptyBookingBlock>
    )

    if (this.state.pastAppointments.length) {
      pastAppointmentsBlock = (
        <BookingBlock>
          {this.state.pastAppointments.map(appt => {
            return <Appointment key={appt.id} appointmentData={appt} />
          })}
        </BookingBlock>
      )
    } else {
      pastAppointmentsBlock = EmptyBlock
    }

    if (this.state.futureAppointments.length) {
      futureAppointmentsBlock = (
        <BookingBlock>
          {this.state.futureAppointments.map(appt => {
            return <Appointment key={appt.id} appointmentData={appt} />
          })}
        </BookingBlock>
      )
    } else {
      futureAppointmentsBlock = EmptyBlock
    }

    return (
      <div>
        <h2>Your bookings</h2>
        {futureAppointmentsBlock}
        {pastAppointmentsBlock}
      </div>
    )
  }
}

From the above, BookingBlock and EmptyBookingBlock are simply styled components without any logic.从上面可以看出, BookingBlockEmptyBookingBlock是简单的样式组件,没有任何逻辑。

The Appointment component is as in this following MWE: Appointment组件如下面的 MWE 所示:

const Appointment = props => {
  const { id, appointmentStart, appointmentEnd, status } = props.appointmentData
  return (
    <AppointmentBlock>
        <p>
          <Description>Start: </Description>
          <Value> {moment(appointmentStart).format('HH:mm')} </Value>
        </p>
        <p>
          <Description>End: </Description>
          <Value> {moment(appointmentEnd).format('HH:mm')} </Value>
        </p>
        <p>
          <Description>Status: </Description>
          <Value>
            {status === 'Confirmed' ? (
              <PositiveValue>Confirmed</PositiveValue>
            ) : (
              <NegativeValue>{status}</NegativeValue>
            )}
          </Value>
        </p>
        <CancelAppointment
          id={id}
          appointmentStart={appointmentStart}
          status={status}
        />
      </div>
    </AppointmentBlock>
  )
}

Again, AppointmentBlock , Description and Value are simply styled components without logic.同样, AppointmentBlockDescriptionValue是没有逻辑的简单样式组件。 CancelAppointment is a component represented by the following MWE, which cancels the appointment via a Mutation : CancelAppointment是由以下 MWE 表示的组件,它通过Mutation取消约会:

const CANCEL_APPOINTMENT = gql`
  mutation cancelAppointment($id: Int!) {
    cancelAppointment(id: $id) {
      id
      appointmentStart
      appointmentEnd
      appointmentType
      status
    }
  }
`

// code omitted for brevity...

class CancelAppointment extends Component {
  constructor (props) {
    super(props)
    const hoursUntilAppt = moment(this.props.appointmentStart).diff(
      moment(),
      'hours'
    )
    const cancellable =
      this.props.appointmentType === 'A'
        ? hoursUntilAppt > 72
        : hoursUntilAppt > 48

    this.state = {
      cancelled: this.props.status === 'Cancelled',
      cancellable,
      firstClick: false
    }
  }

  cancelAppointment = async (e, cancelAppointment) => {
    e.preventDefault()
    await cancelAppointment({
      variables: { id: this.props.id }
    })
  }

  render () {
    if (!this.state.cancelled) {
      if (!this.state.cancellable) {
        return (
          <CancelAppointmentButtonInactive>
            Cancellation period elapsed
          </CancelAppointmentButtonInactive>
        )
      }
      if (!this.state.firstClick) {
        return (
          <CancelAppointmentButtonActive
            onClick={() => {
              this.setState({ firstClick: true })
            }}
          >
            Cancel appointment
          </CancelAppointmentButtonActive>
        )
      } else if (this.state.firstClick) {
        return (
          <Mutation mutation={CANCEL_APPOINTMENT}>
            {cancelAppointment => {
              return (
                <CancelAppointmentButtonActive
                  onClick={e => this.cancelAppointment(e, cancelAppointment)}
                >
                  Are you sure?
                </CancelAppointmentButtonActive>
              )
            }}
          </Mutation>
        )
      }
    } else {
      return (
        <CancelAppointmentButtonInactive>
          Appointment cancelled
        </CancelAppointmentButtonInactive>
      )
    }
  }
}

Once more CancelAppointmentButtonInactive and CancelAppointmentButtonActive are button styled components. CancelAppointmentButtonInactiveCancelAppointmentButtonActive是按钮样式的组件。

The mutation functions as expected and cancels the appointment on the database.突变按预期运行并取消数据库上的约会。 After the mutation function is called the Apollo cache is updated in browser memory to reflect the appointment being cancelled.调用变异函数后,Apollo 缓存会在浏览器内存中更新,以反映被取消的约会。 I have tested this using the Apollo dev tools.我已经使用 Apollo 开发工具对此进行了测试。

However this change in appointment status is not reflected in the UI, in particular the status displayed in AppointmentAppointmentBlock does not update to cancelled.但是,约会状态的这种更改不会反映在 UI 中,尤其是在AppointmentAppointmentBlock中显示的状态不会更新为已取消。 The CancelAppointment button also does not receive an update to its this.props.status as one would expected when the appointment is updated in the cache via the completed mutation. CancelAppointment按钮也不会像预期的那样接收到this.props.status的更新,因为当约会通过已完成的this.props.status在缓存中更新时。

I initially thought this may be down to query/mutation object return object differences, but even after unifying what fields are returned the UI does not update.我最初认为这可能归结为查询/变异对象返回对象的差异,但即使在统一返回哪些字段后,UI 也不会更新。

The data flow of the appointment data is Query 'GET_USER_APPOINTMENTS'BookingBlockAppointmentCancelAppointment .预约数据的数据流向为Query 'GET_USER_APPOINTMENTS'BookingBlockAppointmentCancelAppointment

Your BookingsBlock component is copying first props into own state , therefore change in the props , caused by the mutation, is not affecting the rendered state.您的BookingsBlock组件正在将第一个props复制到自己的state ,因此由突变引起的props更改不会影响渲染状态。 Simply getting rid of the state in BookingsBlock will help - it's not needed in there anyway, as you can easily calculate both pastAppointments and futureAppointments in the render method.简单地摆脱BookingsBlock中的state会有所帮助 - 无论如何都不需要它,因为您可以轻松地在render方法中计算pastAppointmentsfutureAppointments

First you have to change the fetch policy in GET_USER_APPOINTMENTS.首先,您必须更改 GET_USER_APPOINTMENTS 中的获取策略。 cache-first is default . cache-first 是 default 。 network-only always fetches form server it does not look in cache first. network-only 总是从服务器获取它不会首先在缓存中查找。

Second .. after mutation you have to update the cache.第二个 .. 突变后,您必须更新缓存。

check this link from off [ https://www.apollographql.com/docs/react/essentials/mutations.html#update][1]从关闭检查此链接 [ https://www.apollographql.com/docs/react/essentials/mutations.html#update][1]

hope this will help.希望这会有所帮助。 stay blessed :)祝好运 :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM