Apollo Client error when executing a mutation - reactjs

Here again for another question which I can't seem to figure out.
I am using Apollo Client (with react) to communicate with my GraphQL server.
I get an error when I try to perform a mutation and I don't know where the issue is coming from because other mutations work fine.
This is the mutation I'm having an issue with:
const DELETE_USER_MUTATION = gql`
mutation deleteUser($id: ID!) {
deleteUser(id: $id) {
id
}
}
`;
The mutation works fine when I input it in the GraphQL playground...
This is how I call the mutation (triggered by a button click):
<button
onClick={() =>
deleteUser({
variables: {
id: user.id,
},
})
}>
Note: user.id is obtained by performing a query and it is valid.
Finally, this is how the deleteUser function is defined (using the useMutation hook)
const [deleteUser, { error }] = useMutation(DELETE_USER_MUTATION, {
refetchQueries: [{ query: GET_USERS_QUERY }],
});
On a side note, how can one debug such errors? On the console I get an error 400, which I read means that it's probably an error with the mutation itself. But I don't get more information about the error... I tried to catch it but to no avail.
Thank you!

I was able to solve the issue and I can't believe I didn't realize the problem sooner.
After checking the type of user.id, I realized it was a string instead of an integer. Converting it to a an Int worked.
However I'm having some cache issues now... Time for more research

Related

react-query useQuery not refetching after useMutation

I am using react-query (actually tanstack/react-query v4) to query from and mutate a db. Based on docs and research, I gather that useQuery will automatically refetch from the server if/when the server-state differs from the cached state.
However, after I useMutation to update my db, the impacted query does not immediately refetch.
I know that the useMutation is working based on viewing the db on server-side, but also because I can manually refetch using react-query dev tools, and get the new values just fine.
On reading, I have tried two approaches:
the "invalidateQueries" pattern, hoping that the useQuery refetches and re-renders (from the docs on queryInvalidation: "...If the query is currently being rendered via useQuery or related hooks, it will also be refetched in the background")...
const addMover = useMutation({
mutationFn: (newMover) => { ... },
onSuccess: () => {
queryClient.invalidateQueries(["movers"]);
console.log("The mutation is sucessful!");
},
});
---> When this mutation gets run, I do see the 'onSuccess' console.log() coming through, but the query still shows as 'stale' in the dev-tools and does not get re-rendered.
I also tried (in a different place) the "SetQueryData" pattern from the useMutation response, as outlined in the docs...
const handleDelete = useMutation(
{
mutationFn: (wktID) => { ... },
onSuccess: (data) => {
queryClient.setQueryData(["workouts", [activeMover]], data);
},
}
);
My expectation from either approach is simply that the mutated db gets re-queried and re-rendered. I'd prefer to SetQueryData and save a network request, but either approach would make me happy :).
If you want to re-fetch data after mutation you edit your mutation and leave it like this:
const [createHabit, { error, loading }] = useMutation(CREATE_HABIT_MUTATION, {
refetchQueries: [{ query: HABITS_QUERY }],
});
Here you can find an example.

How to call useQuery only once with graphQL?

So I am working on react with GraphQL and I want to call my useQuery only once ,but the problem here is that it executes everytime when page refreshes thus giving the 404 local host error.
Aim :- Want to call this query only once.
const { data, error, loading } = useQuery(getAllData);
I have also tried to achieve this by specifying the condition with useLazyQuery but still no success in that..
let check=true;
useEffect(() => {
if (check) {
check=false;
getEndpoint();
}
},[]);
const [getEndpoint, { data, error, loading }] = useLazyQuery(getAllData);
I am not able to figure any ways how to achieve that..Any Help would be appreciated !

Refetching a query using Apollo-Client throws an error

I am using Apollo-client to post a mutation to my graphql server. When the mutation is completed, I want to refetch that data. I tried using the refetchQueries argument in the useMutation hook, however I receive this error when I execute the code:
query option is required. You must specify your GraphQL document in
the query option.
This is the line of code that sends the mutation:
const [addUser, { data, loading, error }] =
useMutation(ADD_USER_QUERY, {
refetchQueries:[GET_USERS_QUERY]
});
This is my query (the hardcoded arguments were to see if the issues was due to passing variables):
export const ADD_USER_QUERY = gql`
mutation {
createUser(name: "Albert Einstein", email: "albert#yahoo.ca") {
id
name
}
}
`;
Thank you!
Alright so I figured out what the issue was. I had to pass an object with a "query" key in the refetchQueries array:
const [addUser, { data, loading, error }] =
useMutation(ADD_USER_QUERY, {
refetchQueries: [{ query: GET_USERS_QUERY }],
});
It's weird though because it isn't mentioned in the ApolloDocs. They simply use an array...
// Refetches two queries after mutation completes
const [addTodo, { data, loading, error }] = useMutation(ADD_TODO, {
refetchQueries: [
GET_POST, // DocumentNode object parsed with gql
'GetComments' // Query name
],
});
Does anyone know why that is?
Thanks!

Apollo error handling - why react app crashes?

is somebody able to explain, why my react app + apollo behaves like this when I try to use mutation which returns error?
GraphQL mutation returns this (response code is 200): {"errors":[{"error":{"result":"identity.not-found","error":"authentication-failed","statusCode":401}}],"data":{"login":null}}
My mutation looks like this:
export const LOGIN_MUTATION = gql`
mutation($input: LoginInput!) {
login(input: $input) {
token
}
}
`;
called:
const handleSignIn = () => {
loginMutation({
variables: {
input: {
clientId: config.clientId,
username: userName,
password: password,
clientSecret: config.clientSecret
}
}
});
};
It behaves for awhile like expected (my own custom error component is rendered - {error && <div>error</div>}), but then it throws this unhandled rejection.
If I add catch callback to mutation call, it works as expected.
However, I did not find anywhere in apollo docs any mentions about the need to always catch GraphQL errors such way. This should be sufficient, if I understand it correctly: const [loginMutation, {data, loading, error}] = useMutation(LOGIN_MUTATION);
Is this behaviour correct or do I miss something?
Versions:
"#apollo/react-hooks": "^3.1.3"
"apollo-boost": "^0.4.7"
"graphql": "^14.5.8"
The mutate function returns a Promise that, by default, will be rejected if your response includes an errors object or if a network error occurs. If you change the errorPolicy to ignore or all, the presence of errors in your response won't cause the Promise to reject, but a network error still will.
The only way to avoid this behavior is to provide an error handler through the onError parameter. If onError is provided, the Promise returned by mutate will always resolve and any relevant errors (depending on your errorPolicy) will be passed to onError instead.
Additional details on error handling in Apollo can be found here. Additional details on unhandled Promise rejections can be found here.

How to get refetchQueries data in reactjs 16.8

I'm trying to use refetchQueries to get an updated list of record after a mutation. I have tried below code to get updated data but the updated data showing in network tab of the developer console.
This is for reactjs 16.8 and "react-apollo": "^2.5.5" and it seems awaitRefetchQueries: true not working
client.mutate({
mutation: ADD_ACTIVE_CREW,
variables: {
activeCrewInfo: {
employee: activeCrew[0].vp_id,
date_on_crew: new Date(),
crew_id: selectedCrewId
}
},
options: () => ({
refetchQueries: [
{
query: GET_EMPLOYEE_BY_CREW_ID_QUERY,
variables: { crew_id: crew_id }
}
]
}),
awaitRefetchQueries: true
});
I'm getting correct response in developer console's network tab, but not able to access in my reactjs application.
The mutation data itself will never reflect the refetched queries.
Any queries you tell Apollo to refetch will be requested and then have their result written to the cache. That means any Query components or components using useQuery or watchQuery will be updated, provided the query and variables parameters match what's in refetchQueries.
If you don't already have a component that uses that query, you need to add one.

Resources