提交突变后,QueryRenderer不会更新

问题描述

我对中继和GraphQL还是很陌生,希望模仿添加突变后的行为,我的组件会使用新突变进行更新。例如,当我添加动物时,它会显示在我的动物列表中。

我已经阅读了一些有关通过乐观更新,获取容器等手动更新商店的信息,但是想知道是否仅通过使用QueryRenderer HOC和简单的突变就可以发生这种行为。

该变异成功完成,但是刷新页面后我才能看到更新。

这是根查询渲染的代码:

export const Customer = ({ userId }) => {
  return (
    <QueryRenderer
      environment={environment}
      query={query}
      variables={{ userId }}
      render={({ error,props }) => {
        //handle errors and loading
        const user = props.customers_connection.edges[0].node
        return (
          <div className="flex justify-between items-center">
            <h1 className="text-xl">Pets</h1>
            <AddPetForm />
            <PetList user={user} />
          </div>
        )
      }}
    />
  )
}

const query = graphql`
  query CustomerQuery($userId: bigint) {
    customers_connection(where: { userId: { _eq: $userId } }) {
      edges {
        node {
          id
          userId
          pets {
            id
            animal {
              ...Animal_animal
            }
          }
        }
      }
    }
  }
`

这里是Animal组件中的PetList组件。 PetList组件是我希望重新渲染的组件,它将包括一个新的Animal组件,其中包含通过突变创建的动物。


const Animal = ({ animal }) => {

  return (
    <li>
        <Summary animal={animal} />
    </li>
  )
}

export default createFragmentContainer(Animal,{
  animal: graphql`
    fragment Animal_animal on animals {
      name
      category
      imageUrl
      weight
      type
    }
  `
})

这是AddPetForm组件:

const AddPetForm = () => {
  const { hide } = useModal()
  return (
    <Modal>
      <QueryRenderer
        environment={environment}
        query={query}
        variables={{}}
        render={({ error,props }) => {
          //handle errors and loading 
          return (
            <Form
              hide={hide}
              //pass down props from query
            />
          )
        }}
      />
    </Modal>
  )
}

const query = graphql`
  query AddPetFormQuery {
    enum_animal_category_connection {
      edges {
        node {
          id
          value
        }
      }
    }
    //other enums to use in the form
  }
`

以及用于突变的代码(该代码位于AddPetForm组件中):

const Form = ({ hide,...other props }) => {
  const { handleSubmit,register,errors,} = useForm({ defaultValues,resolver })
  const [mutationIsInFlight,setMutationIsInFlight] = useState(false)
  const [mutationHasError,setMutationHasError] = useState(false)

  const onCompleted = (response,error) => {
    setMutationIsInFlight(false)
    if (error) onError(error)
    else showSuccessNotification()
  }

  const onError = error => {
    setMutationIsInFlight(false)
    setMutationHasError(true)
  }

  const onSubmit = animal => {
    setMutationIsInFlight(true)
    setMutationHasError(false)
    //assume animal has already been added
    addAnimalAsPet({ animalId: animal.animalId,userId,onCompleted,onError })
    
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="flex flex-wrap">
      // all of the inputs
      <div className="mt-3 w-full">
        <PrimaryButton type="submit" fullWidth={true} loading={mutationIsInFlight}>
          Save
        </PrimaryButton>
      </div>
      {mutationHasError && <p className="text-red-700 my-3">An error has occurred. Please try again.</p>}
    </form>
  )
}

以及突变代码:

const mutation = graphql`
  mutation addAnimalAsPet Mutation($animalId: Int,$userId: Int) {
    insert_pets_one(object: { animalId: $animalId,userId: $userId }) {
      id
    }
  }
`

export const addAnimalAsPet = ({ userId,animalId,onError }) => {
  const variables = { userId,animalId }
  commitMutation(environment,{
    mutation,variables,onError
  })
}


有什么明显的地方我做错了吗?如您所见,有一个嵌套的QueryRenderer HOC,这会以某种方式破坏自动更新吗?

我没有使用订阅,因为我不需要实时事件监听。仅当用户添加新宠物时,才会更新此数据,并且这种情况不会经常发生。而且我还没有使用过乐观的更新/响应,因为在等待响应之前并不需要真正向用户展示更新是否成功。

从文档中看,似乎有一种方法可以使用“ Refetch容器”来实现,但是必须重构我的代码才能使用片段。

解决方法

xadm的建议很吸引人。有一个retry函数是QueryRenderer render道具中对象的属性。

这是一个可行的示例:

<QueryRenderer
  environment={environment}
  query={query}
  variables={{ userId }}
  render={({ error,props,retry }) => {
    //handle errors and loading
    const user = props.customers_connection.edges[0].node
    return (
      <div className="flex justify-between items-center">
        <h1 className="text-xl">Pets</h1>
        <AddPetForm refreshCustomerQuery={retry} />
        <PetList user={user} />
      </div>
    )
  }}
/>

然后在成功成功突变后,我就简单地调用refreshCustomerQuery函数。

const onCompleted = (response,error) => {
  setMutationIsInFlight(false)
  if (error) onError(error)
  else {
    showSuccessNotification()
    refreshCustomerQuery()
  }
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...