首页 > 解决方案 > 如何使用 react、typescript 和 graphql 更新从查询中获得的值?

问题描述

当从另一个组件单击按钮时,我想更新从 graphql 查询中获得的值。

我想做什么?我有一个 ButtonComponent,它有一个“添加”按钮和标签“计数”,它从名为 getCount 的 graphql 查询中获取一个值。

有一个具有标签“showAvailableCount”的 CountViewComponent,它从名为 getCount 的同一个 graphql 查询中获取值。

此 getCount 查询返回 availablebookscount、availablepenscount、totalbookscount、totalpenscount,如下所示,

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

ButtonComponent 如下所示,

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>
        )
    }
}

在这个组件中单击添加按钮我调用 createItem 突变。在 createItem 突变中,我通过将值减 1 并因此更新 Count 变量来更新可用笔计数的缓存。

createItem 突变如下所示,

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 };
}

结果如下所示,

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

countViewComponent如下所示,

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

单击“添加”按钮时,如何更新此 showAvailableCount 值。ButtonComponent 中的 availablepenscount 变量值会按照缓存的预期进行更新。但在 CountViewComponent 中的工作方式不同。

有人可以帮我解决这个问题。我是使用 typescript 和 graphql 的新手。谢谢。

编辑: 这里有两件事。显示来自查询 GET_COUNT 的数据的 CountViewComponent 和显示与来自查询 GET_COUNT 的 CountViewComponnet 中相同数据的 ButtonComponent。

有一个输入字段。当用户输入电子邮件并单击 ButtonComponent 中的添加按钮时,会调用 createItem 突变以将此电子邮件添加到可用项目列表中。

当用户添加电子邮件时,此可用笔计数值应减少 1。

而不是再次查询graphql服务器以获取此数据...我在创建项目突变期间更新缓存,如上面的代码所示...

直到这里它工作正常......

现在的问题是,这个 countViewComponent 应该与单击添加按钮后的 ButtonComponent 具有相同的值......

在 Buttoncomponent 中更新缓存不会在 countViewComponent 中渲染相同的值......

我该怎么做。任何帮助表示赞赏。谢谢。

Edit2: 根据下面提供的答案,它会在第二次单击添加按钮时更新 countViewComponent 中的计数值

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,
   });
}

标签: reactjstypescriptgraphql

解决方案


别管不使用远程计数器数据...

缓存应该使用不可变的方法来更新——通过创建新对象,而不是现有对象的突变。通过这种方式,阿波罗可以检测/响应变化(并强制更新观察到的查询)。

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

应该

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

    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,
        });

应该是(类似于):

    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
        }
    });

推荐阅读