I'm asking this question because I wasn't able to find any ressource on the web (including SO, but also the documentation of Apollo-Client which is quite laconic on the subject), and I'm a out of solution.
I've got this client-side schema :
const typeDefs = gql'
extend type Query @client {
getMessageSliceByIdMessaging(id_messaging: String!): [MESSAGE_SLICE]!,
}
type MESSAGE_SLICE {
_id: String!,
__typename: String!,
newest_date_creation: String!,
oldest_date_creation: String!,
list_id_message: [MESSAGE]!,
},
'
I've made this typePolicies in the InMemoryCache
typePolicies: {
Query: {
fields: {
getMessageSliceByIdMessaging : {
merge(existing = [], incoming = [], {cache}) {
//Doing some shenanigans
return some_shenanigans
},
read(existing = []) {
return [...existing] //existing properly return "some_shenanigans" generate in merge function
},
}
}
}
}
But, despite the read function returning the correct "some_shenanigans", when I'm calling :
///FRAGMENT OF MESSAGE_SLICE
const MESSAGE_SLICE_FRAGMENT = gql`
fragment MessageSliceFragment on MESSAGE_SLICE {
_id,
newest_date_creation,
oldest_date_creation,
list_id_message {
...messageFragment,
},
},
${MESSAGE_FRAGMENT}
`
///QUERY TO GET A LIST OF MESSAGE_SLICE
const GET_MESSAGE_SLICE_BY_ID_MESSAGING = gql`
query getMessageSliceByIdMessaging (
$id_messaging: String!,
) {
getMessageSliceByIdMessaging @client (
id_messaging: $id_messaging,
) {
...MessageSliceFragment,
},
},
${MESSAGE_SLICE_FRAGMENT}
`
///CALL OF THE QUERY
const messageSliceListData = useQuery(GET_MESSAGE_SLICE_BY_ID_MESSAGING, {
variables: {
id_messaging: route.id_messaging,
},
})
///CALLING THIS ALLOW TO PAST DATA TO THE MERGER (missing context, but work properly)
await client.writeQuery({
query: GET_MESSAGE_SLICE_BY_ID_MESSAGING,
variables: {
id_messaging,
},
data: {getMessageSliceByIdMessaging: [...SOME_ARRAY_DATA_THAT_NEED_TO_BE_MERGE_IN_THE_TYPE_POLICIES]}
})
messageSliceListData?.data
always return [{}]
or undefined
, and I don't get any Error.
Some thing that I've tried :
some_shenanigans
as a reference (using toReference
),some_shenanigans
as raw data.I wasn't able to find a tutorial or other sources treating this question with Apollo 3.0 and typePolicies (apart from this link: https://www.apollographql.com/tutorials/fullstack-quickstart/10-managing-local-state, but it's using reactives variables
, not typePolicies
)
So what is the proper way to implement such a solution ?
N.B : I'm using this in a React-Native App, and I'm not in capacity to use the Apollo Developer Tools.
So, I've resolved my problem, and had succeed in getting my data properly.
There was a typo in my code elsewhere, and sometime the result of useQuery(GET_MESSAGE_SLICE_BY_ID_MESSAGING)
return an undefined
at the second call (easy turnaround with useEffect
).
Howerver, I've test some things and I want to share it if someone else struggle with the populate of local Schema :
You need to return the Schema with raw data for the inner props and with ref for relations.
Example :
For this Schema :
type MESSAGE_SLICE {
_id: String!,
__typename: String!,
newest_date_creation: String!,
oldest_date_creation: String!,
list_id_message: [MESSAGE]!,
},
You need to return an object of this type :
CORRECT_FORMAT_FOR_MESSAGE_SLICE_TO_RETURN = [{
_id: SOME_ID,
__typename: "MESSAGE_SLICE",
newest_date_creation,
oldest_date_creation,
list_id_message: [
{__ref: "MESSAGE:ID_OF_MESSAGE_,"},
{__ref: "MESSAGE:ID_OF_MESSAGE_2"},
]
}]
Returning only the apollo ref of MESSAGE_SLICE will not work :
WRONG_FORMAT_FOR_MESSAGE_SLICE_TO_RETURN = [
{__ref: "MESSAGE_SLICE:ID_OF_MESSAGE_SLICE_1"},
{__ref: "MESSAGE_SLICE:ID_OF_MESSAGE_SLICE_2"},
]
And returning raw data for all MESSAGE_SLICE and relation will not work either:
WRONG_FORMAT_FOR_MESSAGE_SLICE_TO_RETURN = [{
_id: SOME_ID,
__typename: "MESSAGE_SLICE",
newest_date_creation,
oldest_date_creation,
list_id_message: [
{
_id: SOME_ID,
__typename: "MESSAGE",
id_user: "SOME_ID",
content_message: "SOME_CONTENT"
},
{
_id: SOME_ID,
__typename: "MESSAGE",
id_user: "SOME_ID",
content_message: "SOME_CONTENT"
},
]
}]
An another thing, in the defintion of Schema, __typename
isn't mandatory BUT (see below):
type MESSAGE_SLICE {
_id: String!,
__typename: String!, //this line is optionnal, BUT (see below again).
newest_date_creation: String!,
oldest_date_creation: String!,
list_id_message: [MESSAGE]!,
},
BUT, you need to init a __typename in some way.
It's possible to proceed in this way:
CORRECT_FORMAT_FOR_MESSAGE_SLICE_TO_RETURN = [{
_id: SOME_ID,
__typename: "MESSAGE_SLICE", //Init this props in the merger function when creating a new MESSAGE_SLICE
newest_date_creation,
oldest_date_creation,
list_id_message: [
{__ref: "MESSAGE:ID_OF_MESSAGE_,"},
{__ref: "MESSAGE:ID_OF_MESSAGE_2"},
]
}]
Or in this way, using typePolicies :
typePolicies: {
MESSAGE_SLICE: {
fields: {
__typename: {
read() {
return "MESSAGE_SLICE"
}
},
},
},
}
Hoping that this will help someone.