reactjs - 如何使用 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,
});
}
解决方案
别管不使用远程计数器数据...
缓存应该使用不可变的方法来更新——通过创建新对象,而不是现有对象的突变。通过这种方式,阿波罗可以检测/响应变化(并强制更新观察到的查询)。
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
}
});
推荐阅读
- c# - 在具有公共基类的对象上调用受保护的方法
- git - Is it possible to git mv after push?
- node.js - 如何在 CentOS7 上自动启动 node/express 应用程序(使用 pm2),使用软件集合(scl)安装节点
- c# - 当我删除索引 0 时,C# DataRow.Delete() 正在清除 DataTable
- node.js - 如何在谷歌云 puppeteer 函数中传递两个参数?解析为请求到 JSON
- angular - 如何在主路由器插座中使用命名路由器插座?
- python - 查找句子中字符串的完全匹配
- c++ - 如何将 ActiveX-EXE(进程外服务器)嵌入 Excel 电子表格
- web-services - SSRS - 将复杂的参数传递给 Web 服务
- pandas - Pandas - 将多列中的数据(列表)吐到新行中