I've created a graphQL server with following schema:
...
#charts interface
interface Chart {
id: String!
sql: String!
title: String
type: String!
display: String!
}
type Layout{
# Unique layout id
id: String
# The title displayed on the layout tab
title: String
# List of displayed charts
charts: [Chart]
}
...
On my client I have a <SummaryLayout/>
component with the following gql query:
gql`{
layout(id:"summary"){
title
charts {
id,
title,
type,
display
}
}}`
When loading the page the layout component displays all the charts as a grid on the page. The user can later add a new chart, so I have 2 mutations: one creating the chart and the other is adding the new chart to the layout:
const addToLayout = gql`
mutation addToLayout($layoutID: String!, $chartID: String!) {
addToLayout(layoutID: $layoutID ,chartID:$chartID){
id
charts {
id
sql
title
type
display
}
}
}`;
const addChart = gql`
mutation addChart($chartConfig:ChartConfig!) {
addChart(chartConfig:$chartConfig){
id
display
}
}`;
this.props.addChart({
variables: {chartConfig: chartConfig}
}).then((response) => {
const chartID = response.data.addChart.id;
console.log("Chart added, DB ID:", chartID);
this.props.addToLayout({
variables: {layoutID: "summary", chartID: chartID},
update: (store, data) => {
console.log("STORE:",store);
}
}).then((response) => {
appState.toggleDialog(false);
})
});
When I log the store I can see that the Layout:summary
entry is updated, but it is not reflected at the UI, one more thing that popped is that there is another entry called $ROOT_QUERY.layout({"id":"summary"})
that is not updated with the new data:
What am I missing?
By default, InMemoryCache will attempt to use the commonly found primary keys of id and _id for the unique identifier if they exist along with __typename on an object.
If id and _id are not specified, or if __typename is not specified, InMemoryCache will fall back to the path to the object in the query, such as ROOT_QUERY.allPeople.0 for the first record returned on the allPeople root query. That would make data for given type scoped for allPeople query and other queries would have to fetch their own separate objects.
Apollo uses that generated key to determine what to update when your mutation is resolved. What it boils down to is that both your queries and mutations need to include the id. This way the generated key used by both will be the same. In your code, it looks like the mutation includes the layout's id but the query does not.
If for some reason, an id is not available, you can use the dataIdFromObject
option to identify a different field to key off of.