jqueryreactjsapollo-clientgraphql-mutation

Unable to refetch data after mutation with useQuery, useMutation and refetch callback


I have a standard component setup with one component making a query for data and a modal form that mutates entered data on submit. The useQuery hook sets state with the onCompleted callback. I've also added a refetch callback in my useQuery hook, pass it down to the form modal and call it onCompleted in the useMutation hook. I'm unable to get the data to render immediately without having to refresh the page.

The query:

 const {
    loading: childProfilesLoading,
    error: childProfilesError,
    refetch: refetchChildProfiles,
  } = useQuery<any>(GET_CHILD_PROFILES, {
    notifyOnNetworkStatusChange: true, // I was told this might help
    variables: { value: 5 },
    onCompleted: (childProfilesData) =>
      setChildProfiles(childProfilesData?.childProfiles),
  })

and the mutation in the modal form:

  const [
    createChildProfile,
    { error: createProfileError, loading: createProfilePending },
  ] = useMutation<any>(CREATE_CHILD_PROFILE, {
    onCompleted: () => refetchChildProfiles(),
  })

This doesn't add the new data to the parent data in state and doesn't get re-iterated:

 {!!childProfiles.length && (
            <TouchableOpacity onPress={() => setShowModal(!showModal)}>
              <Text style={styles.createText}>+ Add child</Text>
            </TouchableOpacity>
          )}
    // ....more jsx data here


Solution

  • Seems related to https://github.com/apollographql/react-apollo/issues/3709.

    As a workaround, you can rely on the data attribute of the query with a useEffect :

    const {
        loading: childProfilesLoading,
        error: childProfilesError,
        refetch: refetchChildProfiles,
        data: childProfilesData,
      } = useQuery<any>(GET_CHILD_PROFILES, {
        notifyOnNetworkStatusChange: true, // I was told this might help
        variables: { value: 5 },
      })
    
    useEffect(() => {
       setChildProfiles(childProfilesData?.childProfiles),
    }, [childProfilesData, setChildProfiles])
    

    Or event better, use the data attribute directly instead of storing it in another state.