I really like the graphQL pattern of having components request their own data, but some data properties are expensive to compute and so I want to localize the logic (and code) to do so.
function CheaterList({ data: { PlayerList: players } }) {
return (
<ul>
{players && players.map(({ name, isCheater }) => (
<li key={name}>{name} seems to be a {isCheater ? 'cheater' : 'normal player'}</li>
))}
</ul>
);
}
export default graphql(gql`
query GetList {
PlayerList {
name,
isCheater
}
}
`)(CheaterList);
The schema looks like:
type Queries {
PlayerList: [Player]
}
type Player {
name: String,
kills: Integer,
deaths: Integer
}
And so I want to add the isCheater
property to Player and have its code be:
function computeIsCheater(player: Player){
// This is a simplified version of what it actually is for the sake of the example
return player.deaths == 0 || (player.kills / player.deaths) > 20;
}
How would I do that?
Another way of phrasing this would be: how do I get the isCheater property to look as though it came from the backend? (However, if an optimistic update were applied the function should rerun on the new data)
Note: Local state management is now baked into apollo-client
-- there's no need to add a separate link in order to make use of local resolvers and the @client
directive. For an example of mixing local and remote fields, check out of the docs. Original answer follows.
As long as you're using Apollo 2.0, this should be possible by utilizing apollo-link-state
as outlined in the docs.
Modify your client configuration to include apollo-link-state
:
import { withClientState } from 'apollo-link-state';
const stateLink = withClientState({
cache, //same cache object you pass to the client constructor
resolvers: linkStateResolvers,
});
const client = new ApolloClient({
cache,
link: ApolloLink.from([stateLink, new HttpLink()]),
});
Define your client-only resolvers:
const linkStateResolvers = {
Player: {
isCheater: (player, args, ctx) => {
return player.deaths == 0 || (player.kills / player.deaths) > 20
}
}
}
Use the @client directive in your query
export default graphql(gql`
query GetList {
PlayerList {
name
kills
deaths
isCheater @client
}
}
`)(CheaterList);
However, it appears that combining local and remote fields in a single query is currently broken. There's an open issue here that you can track.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With