【问题标题】:How to update value got from a query on clicking a button in another component using react, typescript and graphql?如何使用 react、typescript 和 graphql 更新从查询中获得的值?
【发布时间】:2020-08-19 22:10:56
【问题描述】:

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

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

CountViewComponent 的标签为“showAvailableCount”,它从名为 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 变量来更新 availablepenscount 的缓存。

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 中渲染相同的值......

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

编辑2: 根据下面提供的答案,它会在第二次单击添加按钮时更新 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,
   });
}

【问题讨论】:

  • 谢谢,请您详细解释一下。
  • sorry..我是新来使用 graphql 和 typescript,我没有清楚地明白这一点。所以我应该在 CountViewComponent 中创建一个状态吗?你能告诉我sn-p指向如果不完整要做什么吗?只是想得到jist。谢谢。
  • 这个更新的值已经在数据库中......我应该查询它以获取新值......我在创建突变时更新了缓存,因为这很容易做到......但实际上我们有数据库中的更新值准备好了......或者我被建议做的事情。
  • 抱歉...你应该使用变异结果 (data) 来变异缓存,而不是读取数据 - 请参阅 apollographql.com/docs/react/data/mutations/… ({ data: { addTodo } }) - addTodo 已写入缓存
  • 你的查询和变异结果是同一类型的吗?您可以尝试只使用cache.writeQuery({ query: GET_COUNT, data });(其中数据表示/快捷方式data:data

标签: reactjs typescript graphql


【解决方案1】:

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

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

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

【讨论】:

  • thanks.so 这是否会更新 countViewComponent 中的值以及添加按钮单击?
  • 应该更新使用了这两个查询的任何组件
  • 不知何故它对我不起作用..它现在也没有为 ButtonComponent 更新。
  • 实际上没有,我根据您的回答将其更改为我的问题(在edit2部分下)中的代码,并在第二次单击添加按钮时更新。例如,如果计数值为 4,则单击添加 btn 会将 Buttoncomponent 中的计数值设置为 3,而 countViewComponent 保持为 4。再次单击添加 btn 会将 ButtonComponent 和 countViewComponent 中的值设置为 3。我不确定出了什么问题。
  • 通常(很多情况下,出于同样的原因在 redux 中自然需要)比较对象引用 - 相同的对象(相同的 ref)突变不会被检测为更改 ... immutable.js 强制/帮助更深入的更新
猜你喜欢
  • 2020-02-27
  • 2019-12-09
  • 2020-09-22
  • 1970-01-01
  • 2021-10-03
  • 2018-08-04
  • 1970-01-01
  • 2020-04-26
  • 2018-11-22
相关资源
最近更新 更多