突变更新 apollo 缓存但缓存更新未反映在 UI

Mutation updates apollo cache but cache update not reflected in UI

我将 Apollo Client 与 React 结合使用,我在下面的 MWE 中概述了我的 Query/Mutation 用法。

我有一个 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>

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>
    )
  }
}

从上面可以看出,BookingBlockEmptyBookingBlock是没有任何逻辑的简单样式组件。

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>
  )
}

同样,AppointmentBlockDescriptionValue 是没有逻辑的简单样式组件。 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>
      )
    }
  }
}

再次 CancelAppointmentButtonInactiveCancelAppointmentButtonActive 是按钮样式的组件。

突变按预期运行并取消了数据库上的约会。在调用突变函数后,Apollo 缓存在浏览器内存中更新以反映约会被取消。我已经使用 Apollo 开发工具对此进行了测试。

但是UI中并没有反映预约状态的这种变化,特别是AppointmentAppointmentBlock中显示的状态不会更新为已取消。 CancelAppointment 按钮也没有收到其 this.props.status 的更新,正如人们预期的那样,当约会通过完成的突变在缓存中更新时。

我最初认为这可能归结为 query/mutation 对象 return 对象差异,但即使在统一 return 编辑的字段后,UI 也不会更新。

预约数据的数据流为Query 'GET_USER_APPOINTMENTS'BookingBlockAppointmentCancelAppointment.

您的 BookingsBlock 组件正在将 first props 复制到自己的 state,因此 props 中的更改由突变不影响渲染状态。简单地去掉 BookingsBlock 中的 state 会有所帮助 - 无论如何都不需要它,因为您可以轻松地计算 render 中的 pastAppointmentsfutureAppointments方法。

首先,您必须更改 GET_USER_APPOINTMENTS 中的获取策略。缓存优先是默认的。 network-only 总是从它不在缓存中查找的服务器获取。

其次 .. 突变后你必须更新缓存。

关闭此 link [https://www.apollographql.com/docs/react/essentials/mutations.html#update][1]

希望这会有所帮助。 祝你幸福:)