0
votes

i want to update the value i got from the graphql query when a button is clicked from another component.

What i am trying to do? I have a ButtonComponent that has a "Add" button and label "count" which gets a value from graphql query named getCount.

There is CountViewComponent that has label "showAvailableCount" which gets value from same graphql query named getCount.

This getCount query returns availablebookscount, availablepenscount, totalbookscount, totalpenscount and is like below,

export const GET_COUNT = gql`
    query GetCount {
        getCount {
            totalpenscount
            totalbookscount
            availablepenscount
            avaialbalebookscount
        }
    }
`;

The ButtonComponent is like below,

function ButtonComponent () {
    const { count } = useGetCount();
    const availablepenscount = count.availablepenscount;
    const onAdd = async () => {
        await createItem({ email: email, Id: id }); //this is the mutation
    };
    render = () => {
        return (
            <button onClick={onAdd}>Add</button>
            <span>Count</span>
            <span>{availablepenscount}</span>
        )
    }
}

In this component on clicking add button i call createItem mutation. within createItem mutation i update the cache for availablepenscount by decreasing the value by 1 and hence updating the Count variable.

the createItem mutation looks like below,

const createItem = (variables: CreateInput) => {
    return mutation({
        variables,
        update: (cache, {data}) => {
            if (!data) return;

        const ListCache: any = cache.readQuery({ query: LIST_ITEMS });
        ListCache.listItems.push(data.createItem);
        cache.writeQuery({ query: LIST_ITEMS, data: ListCache });
        const cacheData: any = cache.readQuery({query: GET_COUNT});
            cacheData.getCount.availablepenscount--;//updating 
            //availablepencount from cache
            cacheData.getCount.availablebookscount--;
            cache.writeQuery({
                query: GET_COUNT,
                data: cacheData,
            });
        },
    });
    return { createItem, result };
}

and the result looks like below,

createItem:
    email: "some_email.com"
    id: "1"

the countViewComponent looks like below,

function countViewComponent () {
    const { count } = useGetCount();
    const availablepenscount = count.availablepenscount;
    render = () => {
        return (
            <span>ShowAvailable</span>
            <span>{availablepenscount}</span>
        )
    }
}

How can i update this showAvailableCount value when Add button is clicked. the availablepenscount variable value in ButtonComponent updates as expected with the cache. but doesnt work the same within CountViewComponent.

Could someone help me fix this. I am new to using typescript and graphql. Thanks.

EDIT: Here there is two things. CountViewComponent that shows the data from the query GET_COUNT and the ButtonComponent that shows the same data as in CountViewComponnet from the query GET_COUNT.

there is one input field. when user enters email and clicks add button from ButtonComponent, createItem mutation is called to add this email to list of available items.

When user adds email this availablepencount value should decreaase by 1.

Rather than querying graphql server again for this data...i update the cache during create item mutation as seen from code above...

until here it works fine...

Now the question is, this countViewComponent should have the same value as the ButtonComponent after add button clicked....

updating cache in Buttoncomponent isnot rendering the same value in countViewComponent......

How can i do it. Any help is appreciated. thanks.

Edit2: Based on answer provided tried below, and it updates the count value in countViewComponent on clicking add button for second time

update: (cache, { data }) => {
   const cacheData: any = cache.readQuery({ query: GET_COUNT });
   cacheData.getCount.totalpenscount = 
       cacheData.getCount.totalpenscount + 0;
   cacheData.getCount.totalbookscount = 
       cacheData.getCount.totalbookscount + 0;
   cacheData.getCount.availablepenscount = 
       cacheData.getCount.availablepenscount + 1;
   cacheData.getCount.availablebookscount = 
       cacheData.getCount.availablebookscount + 0;
   cacheData.__typename = 'Count';
   cache.writeQuery({
       query: GET_COUNT,
       data: cacheData,
   });
}
1
thanks could you please explain it in more detail.someuser2491
sorry..i am new to using graphql and typescript and i am not clearly getting the point.so should i create a state in the CountViewComponent? could you show me the snippet pointing to what to be done if not full. just want to get the jist. thanks.someuser2491
this updated value is already in database...i should query it to get new values...i updated cache in create mutation since that was easy to do....but actually we have the updated values in db ready... or something that i was suggested to do.someuser2491
sorry ... you should use mutation result (data) to mutate cache, not readed data - see apollographql.com/docs/react/data/mutations/… ({ data: { addTodo } }) - addTodo is written to cachexadm
your query and mutation result are the same type? you can try to just cache.writeQuery({ query: GET_COUNT, data }); (where data means/shortcut data:data)xadm

1 Answers

0
votes

Leaving alone not using remote counters data...

Cache should be updated using immutable methods - by creating new objects, not by mutations of existing ones. This way apollo can detect/react on change (and force updates of observed queries).

    const ListCache: any = cache.readQuery({ query: LIST_ITEMS });
    ListCache.listItems.push(data.createItem);
    cache.writeQuery({ query: LIST_ITEMS, data: ListCache });

should be

    // concat returns a new array
    const newList: any = cache.readQuery({ query: LIST_ITEMS }).concat (data.createItem); 
    cache.writeQuery({ query: LIST_ITEMS, data: newList });

and

    const cacheData: any = cache.readQuery({query: GET_COUNT});
        cacheData.getCount.availablepenscount--;//updating 
        //availablepencount from cache
        cacheData.getCount.availablebookscount--;
        cache.writeQuery({
            query: GET_COUNT,
            data: cacheData,
        });

should be (something like):

    const cacheData: any = cache.readQuery({query: GET_COUNT});
    const newCounter: any = { ...cacheData.getCount }; // new object
    newCounter.availablepenscount--;//updating properties
    newCounter.availablebookscount--;
    cache.writeQuery({
        query: GET_COUNT,
        data: {
          __typename: 'Count',
          getCount: newCounter
        }
    });