我创建了一个基本示例,该示例从graphql服务器读取数据。 我发现执行突变后,网络呼叫会发出请求。 我正在尝试更新缓存以阻止该网络调用,但是当我尝试读取缓存时。
此方法可检索数据,但不会自动从缓存中读取:
const { data } = useQuery(GET_PLAYERS);
const GET_PLAYERS = gql`
query getPlayers {
players @client {
__typename
_id
name
score
}
}
`;
const { data } = useQuery(GET_PLAYERS);
err =
MissingFieldError {消息:“在ROOT_QUERY对象上找不到字段'玩家'”,路径:Array(1),查询:{…},变量:{…}} 消息:“在ROOT_QUERY对象上找不到字段'玩家'”
const obj = client.readQuery({ query: GET_PLAYERS });
这是我的完整代码。
import React, { FC } from 'react';
import 'cross-fetch/polyfill'; // patch for tests: Error: fetch is not found globally and no fetcher passed, to fix pass a fetch for your environment
import {
gql,
useQuery,
useMutation,
ApolloClient,
InMemoryCache,
ApolloProvider
} from '@apollo/client';
const uri = 'http://localhost:4000/graphql';
const client = new ApolloClient({
uri,
cache: new InMemoryCache()
});
const ADD_PLAYER = gql`
mutation AddPlayer($name: String!) {
addPlayer(player: { name: $name }) {
_id
name
score
}
}
`;
// example with directive = @client to try to get cached version
// const GET_PLAYERS = gql`
// query getPlayers {
// players @client {
// __typename
// _id
// name
// score
// }
// }
// `;
const GET_PLAYERS = gql`
query getPlayers {
players {
_id
name
score
}
}
`;
interface IData {
data: {
players: Array<{ name: string }>;
};
loading: boolean;
}
interface IPlayer {
name: string | null;
}
const App: FC = () => {
const { data } = useQuery(GET_PLAYERS);
// const { data } = client.readQuery({ query: GET_PLAYERS });
// console.log('obj = ', obj);
// const data = obj && obj.data;
const [addPlayer] = useMutation(ADD_PLAYER, {
update: (cache, { data: mutationData }) => {
try {
const cacheGetPlayers: { players: Array<IPlayer> } | null = cache.readQuery({
query: GET_PLAYERS
});
const cachePlayers: Array<IPlayer> = (cacheGetPlayers && cacheGetPlayers.players) || [
{ name: null }
];
let playersUpdated: Array<IPlayer> = { ...cachePlayers };
const player = mutationData.addPlayer;
if (player) {
// ie not already existing !!!
if (playersUpdated) {
if (!cachePlayers.find((item: IPlayer) => player.name !== item.name)) {
playersUpdated.push(player);
}
} else {
playersUpdated = [player];
}
cache.writeQuery({
query: GET_PLAYERS,
data: {
getPlayers: {
players: playersUpdated
}
}
});
}
} catch (err) {
console.log('err = ', err);
}
}
});
const handleClick = () => {
const name = 'mary';
addPlayer({
variables: { name },
// example data:
// optimisticResponse: {
// __typename: 'Mutation',
// addPlayer: {
// _id: ObjectId('4edd40c86762e0fb12000003'), // 4edd40c86762e0fb12000003
// score: 0,
// name
// }
// },
refetchQueries: [{ query: GET_PLAYERS }]
});
};
return (
<div>
list of existing names = {data &&
data.players instanceof Array &&
data.players.map((item: { name: string }) => `,${item.name}`)}
<button type="button" onClick={handleClick}>
Click to add player
</button>
</div>
);
};
const Prov = () => (
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
export default Prov;
任何建议,谢谢
答案 0 :(得分:0)
首先,@client指令仅用于查询数据,您应该使用players
在缓存中启动__typename
字段。像这样:
const cache = new InMemoryCache()
const client = new ApolloClient({
cache,
link,
})
cache.writeData({
data: {
players: {
items: [],
__typename: Player
}
},
})
...
const GET_PLAYERS = gql`
query {
players @client {
__typename
items {
_id
name
score
}
}
}
`;
const { data } = useQuery(GET_PLAYERS);
第二,如果要在mutation之后更新缓存,则应使用update
选项。像这样:
useMutation(UPDATE_PLAYER, {
update(cache, { data: { player } }) {
const { players } = cache.readQuery(options)
cache.writeQuery({
...options,
data: {
players: { ...players, items: [player, ...players.items] },
},
})
},
}
}
)