to perform multiple dependent mutation - grandstack apollo graphql 3.3 - reactjs

I've a bit of confusion how to perform multiple mutation in graphql.
I've read articles about using of graphql() function or compose() function, but i haven't understood if these are the legacy way to do it (version 2)
or is still a valid way to proceed.
I'm currently using apollo 3.3 with grandstack and in my component i do the following to perform a mutation (i used useMutation() hook provided by ApolloClient)
const CreateFBUser = gql `
mutation CreateFBUser($name: String, $fbId: String!) {
CreateFBUser(name: $name, fbId: $fbId) {
_id
id
fbId
name
}
}
`
function FbUserForm() {
const { id } = useParams()
const [formState, setFormState] = useState({})
const [createFBUser,{data: createData}] = useMutation(CreateFBUser)
const { loading, error, data } = useQuery(FBUser,{
variables: {_id: id}
});
...
..
.
as you can see, i havent used components like <Query>, and so on..
FIRST QUESTION: is this component related to the apollo old version? are still regulary used or useMutation() hook is the first choice in apollo 3?
SECOND QUESTION: i need to perform a second mutation related to the first, and i need the generated id from the first mutation to execute the second
//the first mutation
const CreateFBUser = gql `
mutation CreateFBUser($name: String, $fbId: String!) {
CreateFBUser(name: $name, fbId: $fbId) {
_id
id
fbId
name
}
}
`
//the second mutation (pseudocode)
const AddFBUserMemberOf = gql`
mutation AddFBUserMemberOf($from: _GroupInput!, $to: _FBUserInput!) {
AddFBUserMemberOf(from: $from, to: $to) {
from
to
}
}
`
moreover, the second mutation should be performed conditionally according to a value/a variable/something else

The render prop components are deprecated and will not receive further updates or bug fixes according to the docs
For your second question; the mutation function returned from useMutation takes an onCompleted property in the options parameter that executes after the mutation successfully completes.
const [createFBUser,{data: createData}] = useMutation(CreateFBUser)
const [addFBUserMemberOf] = useMutation(AddFBUserMemberOf)
createFBUser({
variables: {
//...
},
onCompleted: (data) => {
// data contains the result of createFBUser
addFBUserMemberOf({
variables: {
//...
}
})
}
})

Related

Send Apollo GraphQL mutation request from React to Contentful

I have a simple app built using React + contentful, I'm using apollo as a client.
I have a simple array of objects which I retrieve using query and which I'd like to update directly from UI.
this is my query
export const GET_RADIO = gql`
query getUrl {
allContentfulRadioUrl {
nodes {
url
radioName
}
}
}
`;
it works fine.
Then this is my mutation:
export const NEW_RADIO = gql`
mutation addNewRadio($url: String!, $name: String!) {
newRadio(url: $url, radioName: $name) {
allContentfulRadioUrl {
nodes {
url
radioName
}
}
}
}
`;
I'm passing the data to the mutation in this way:
const [addRadio] = useMutation(NEW_RADIO);
const submit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
addRadio({
variables: { url: formState.url, radioName: formState.radioName },
});
};
but I keep having errors in the response:
GraphQLError: Variable "$name" of required type "String!" was not provided."
It's my first time using GraohQL and this stack so I'm sure I'm missing something.
what do I did wrong?
I've just found out that the plugin gatsby-source-contentful is only for querying data and not for mutations, so i was trying to do something impossible

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!

`useLazyQuery` From Apollo Seems To Trigger Infinite Render Loop

I try to write a Shopify component using Next.js and the Apollo Client. This is my cart component, which always enters an infinite loop (hundreds of renders per second):
import { gql, useLazyQuery } from "#apollo/client"
export default function Cart() {
const checkoutCreateMutation = gql`
mutation checkoutCreate($input: CheckoutCreateInput!) {
checkoutCreate(input: $input) {
checkout {
id
}
}
}
`
const cartLineItemsQuery = gql`
query ($id: ID!) {
node(id: $id) {
id
}
}
`
const cartId = "MY_CART_ID"
const [getCartItems, data] = useLazyQuery(cartLineItemsQuery)
getCartItems({ variables: { id: cartId } })
return (
<p>This is your data: {JSON.stringify(data)}</p>
)
}
I suspect that my queries may be wrongly formatted, but I'd still like to have an error thrown in this case instead of the infinite loop. Or could the problem also be located outside of that component? When I delete the getCartItems(...) line, no infinite loop occurs.
The reason I use useLazyQuery instead of useQuery is that this code is already reduced, originally I first look if a cart ID exists in the cache and if this is not the case I request a new cart ID, otherwise I query the content of the cart.
I misunderstood the idea behing useLazyQuery. It functions more similar to useMutation, where the execution triggers a rerendering. In my case, the working solution was to use useQuery with a skip parameter, so the query will only execute if, e.g., the cart ID variable is defined.

Apollo client - mutation detect mutation completion and then run code

I am trying to implement an update function and therefore, I am using GraphQL mutation. However, I need to be able to detect when a mutation completes so I can run a refresh function.
So far for the mutation I have:
const handleParameterUpdate = () => {
let active = true;
(async() => {
await updateParameterMutation({variables: {
parameterId: props.parameter.id,
newField: newFieldValue;
}});
if (!active) {
return;
}
})().then(props.updateParams());
}
Inside my parent component I have:
const handleRefresh = () => {
refetchJobParams({
id: parent.id
});
}
My intention is to run the handleRefresh function after the mutation is completed. So far it immediately runs after the handleParametersUpdate therefore, I need to refresh to get new the new parameters.
I don't see your useMutation here. However, there's an option for the useMutation hook to add a onCompleted callback which will get called on success. If you're also refetching something from an apollo query, then I can suggest that you also use refetchQueries options. This lets you write less code & let Apollo handle deal with the refetching & completion callbacks.
Mutation options (onCompleted & refetchQueries)
With your code though, if you wanted to run handleRefresh inside handleParameterUpdate, then you can extract whatever value is returned by your mutation.
const handleParameterUpdate = async () => {
const returnValue = await updateParameterMutation({variables: {
parameterId: props.parameter.id,
newField: newFieldValue;
}});
// whatever check you need to do on your mutation,
if (returnValue){
handleRefresh();
}
}

How to update apollo store after making a mutation in react-native? [duplicate]

This question already has an answer here:
Auto-update of apollo client cache after mutation not affecting existing queries
(1 answer)
Closed 3 years ago.
I am new in this apollo graphql and I justtry to understand how this update store works as every time when I make a mutation I have to refresh my app to see the changes. In my following example I am adding a card in my wallet. So to see the new card in my app I have to reload the app.
This part is from AddCard.js where I cand only add the card but I can't see it. So soon as I make the mutation and goBack() my card is not showing until I reload the app.
Any idea how to fix this?
const GET_ME = gql`
query me {
me {
_id
}
}
`;
const GET_WALLET = gql`
query getUserWallet($u_id: ID!) {
getUserWallet(u_id: $u_id) {
_id
}
}
`;
const CREATE_CARD = gql`
mutation($wallet_id: ID!, $cardNo: String!, $exp: String!, $cvc: String!, $card: String! $user: ID!) {
createPayment(wallet_id: $wallet_id, cardNo: $cardNo, exp: $exp, cvc: $cvc, card: $card, user: $user) {
_id
}
}
`;
const mutationConfig = {
props: ({ mutate }) => ({
createPayment: (wallet_id, cardNo, exp, cvc, card, user) => mutate({
variables: { wallet_id, cardNo, exp, cvc, card, user }
}),
})
}
export default compose(
withApollo,
graphql(GET_ME, { name: "getMe" }),
graphql(GET_WALLET, {
name: "getWallet",
options: (props) => (
{
variables:
{
u_id: props.getMe.me._id
}
}
)
}),
graphql(CREATE_CARD, mutationConfig)
)(AddCard);
Apollo's documentation has been updated to use render props rather than the higher order component. If you check out the section on updating the cache it will show you how to do it. It should work similar for your higher order component. You could pass in an update option, which should give you access to the cache. From there, you can write directly to the cache with writeData/writeQuery or you can alter a fragment with writeFragment.
I hope this helps!

Resources