Relay mutation. FatQuery. Ask all fields in REQUIRED_CHILDREN - reactjs

My question is: i have a mutations config where i have a REQUIRE_CHILDREN config with children array of queries. How can i get all possible fields from a payload object?
{
type: 'REQUIRED_CHILDREN',
children: [
Relay.QL`
fragment on MyPayload {
me {
id
...others field
}
}`]
So how can i ask all possible fields from me object? If i point only fragment on MePayload { me } object relay still returns me me { id }. I want relay to return me all fields in me object. Thanks.

You can't - your client code needs to specify all the fields you want to fetch explicitly. Those fields are then statically validated by the babel-relay-plugin, etc.
You probably don't want to be using REQUIRED_CHILDREN either, by the way. That's only useful to fetch fields that are only accessible in the onSuccess callback of the mutation, and therefore are never written to the Relay store and accessible to Relay containers...

Related

Cannot return documents based off a sorted index using Fauna DB

I'm bumbling my way through adding a back-end to my site and have decided to get acquainted with graphQL. I may be structuring things totally the wrong way, however from following some tutorials I have a React front-end (hosted on Vercel), so I have created an api folder in my app to make use of Vercel's serverless functions. I'm using Apollo server and I decided to go with Fauna as my database.
I've successfully been able to return an entire collection via my API. Now I wish to be able to return the collection sorted by my id field.
To do this I created an index which looks like this:
{
name: "sort_by_id",
unique: false,
serialized: true,
source: "my_first_collection",
values: [
{
field: ["data", "id"]
},
{
field: ["ref"]
}
]
}
I then was able to call this via my api and get back and array, which simply contained the ID + ref, rather than the associated documents. I also could only console log it, I assume because the resolver was expecting to be passed an array of objects with the same fields as my typedefs. I understand I need to use the ref in order to look up the documents, and here is where I'm stuck. An index record looks as follows:
[1, Ref(Collection("my_first_collection"), "352434683448919125")]
In my resolvers.js script, I am attempting to receive the documents of my sorted index list. I've tried this:
async users() {
const response = await client.query(
q.Map(
q.Paginate(
q.Match(
q.Index('sort_by_id')
)
),
q.Lambda((ref) => q.Get(ref))
)
)
const res = response.data.map(item => item.data);
return [... res]
}
I'm unsure if the problem is with how I've structured my index, or if it is with my code, I'd appreciate any advice.
It looks like you also asked this question on the Fauna discourse forums and got an answer there: https://forums.fauna.com/t/unable-to-return-a-list-of-documents-via-an-index/3511/2
Your index returns a tuple (just an array in Javascript) of the data.id field and the ref. You confirmed that with your example result
[
/* data.id */ 1,
/* ref */ Ref(Collection("my_first_collection"), "352434683448919125")
]
When you map over those results, you need to Get the Ref. Your query uses q.Lambda((ref) => q.Get(ref)) which passes the whole tuple to Get
Instead, use:
q.Lambda(["id", "ref"], q.Get(q.Var("ref")))
// or with JS arrow function
q.Lambda((id, ref) => q.Get(ref))
or this will work, too
q.Lambda("index_entry", q.Get(q.Select(1, q.Var("index_entry"))))
// or with JS arrow function
q.Lambda((index_entry) => q.Get(q.Select(1, index_entry)))
The point is, only pass the Ref to the Get function.

Updating Array of Objects in Firebase Realtime Database in React js

I have a problem with updating certain properties of an array of objects in a real-time database in Firebase.
My object looks like the following (see picture).
Now I want to update the IsComing property of the second participant object.
At the moment I use the updateIsComming() function, but this is not very convincing, because I have to rewrite the whole object.
function updateIsComming() {
const db = getDatabase();
update(ref(db, " your_path/EventModel/" + modelkey ), {
Location: "London",
Participants: [
{ Name: "Bella2", IsComming: "true" },
{ Name: "Tom", IsComing: "true" },
],
});
Instead, I just want to reference the specific prop from that array. For example
Participant[1].IsComming = false;
Is there any way I can access a specific array of an object directly.
Arrays as a data structure are not recommended in Firebase Realtime Database. To learn why, I recommend reading Best Practices: Arrays in Firebase.
One of the reasons for this is that you need to read the array to determine the index of the item to update. The pattern is:
Read the array from the database.
Update the necessary item(s) in the array in your application code.
Write the updated array back to the database.
As you already discovered, this is not ideal. As is common on NoSQL databases, consider an alternative data structure that better suits the use-case.
In this case, an alternative data structure to consider is:
Participants: {
"Bella2": true,
"Tom": true
}
In there, we use the name of the participant as the key which means:
Each participant can be present in the object only once, because keys in an object are by definition unique.
You can now update a user's status by their name with: update(db, "your_path/EventModel/" + modelkey + "/Participants/Tom", false).

Apollo Client readFragment with custom id (keyFields)

For ref, using "#apollo/client": "^3.5.5",
I've defined my typePolicies like so as suggested in docs:
HistoricalData: {
keyFields: ["variable", "workspace"],
fields:{...}
}
and when my cache is built, I am expecting my cacheId to be like
<__typename>:<id>:<id>
HistoricalData:${props.variable}:${props.workspace}`;
but instead, when I look in the Apollo cache, it's been created using the keyField names and the values in an object, such as
HistoricalData:{"variable":"GAS.TOTAL","workspace":"ABC"}
instead of
HistoricalData:GAS.TOTAL:ABC
so when I try to readFragment it returns null
client.readFragment({
id: `HistoricalData:${props.variable}:${props.workspace}`,
fragment: apolloGQL`fragment MyHistorical on Historical {
variable
workspace
}`})
It does actually return a value from the cache if I create my id in the structure that exists in the cache and readFragment using this.
Has anyone else noticed that Apollo client is not creating the cache id's in the structure that they describe in the docs?
After some research I came upon the correct way to handle this case. I know that you have already moved on, but just in case anyone else has the same problem in the future, here goes:
As described in the documentation for customizing the cache ID, the cache ID will be an stringified object, as you pointed out. It's not quite explicit in the documentation, but at this point in time it provides this nested example for a cache ID:
Book:{"title":"Fahrenheit 451","author":{"name":"Ray Bradbury"}}
But as users we don't have to preoccupy us with the format of this ID, because there's a helper for that, called cache.identify.
For your specific case, you could use something like this:
const identifiedId = cache.identify({
__typename: 'HistoricalData',
variable: 'GAS.TOTAL',
workspace: 'ABC'
});
cache.readFragment({
id: identifiedId,
fragment: apolloGQL`fragment MyHistorical on Historical {
variable
workspace
}`
});

cache.writeFragment method in graphQL apollo library doesn't work

I'm trying to add a property to an object already in cache.
I have added local resolver and in that i'm doing this.
cache.writeFragment({
id: gid.toString(),
fragment: gql`
fragment queues on Group {
queuesList
}
`,
data: {
queuesList: ["test"],
__typename: "Group"
}
});
This writes an object to cache and does not add a property to object of given Id.
I don't understand where does fragment fail.
Okay, I was doing it wrong.
I was giving fragment wrong id, I had to pass the object keys in cached data.
That is. id: Group:${gid.toString()}
https://www.apollographql.com/docs/react/caching/cache-configuration/#generating-unique-identifiers
Hope this helps anyone in same situation.

map big json object to model object in typescript

I have array of object, each object contains;
{
Id:"..",
name:"..",
foo1:"..",
foo2:"..",
...
}
I need only 2 properties of these items so I have created an interface;
export interface IMenuModel{
Id:number;
name?:string;
}
and retrieve data within this method below:
fetch(`..`).then((response: Response): Promise<{ value:IMenuModel[] }> => {
return response.json();
})
.then((response: { value: IMenuModel[] }): void => {
debugger //expected response is array of IMenuModel but it still contains all properties
I expect this response object as array of my custom model(IMenuModel) but it still contains all properties retrieved from remote source.
I can pluck them with ".map()" function thats ok but there is return type defined to function(response: { value: IMenuModel[] }) so I shouldnt have to do this(or do I have to map it manually each time).
Why still response not in my object model and whats the most efficient way to achieve this?
TypeScript is mostly a type layer on top of JavaScript. These typings do not change the typed object. When transpiled into JavaScript the typings are simply dropped. If you apply an interface (or multiple interfaces) to your JSON object, you don't change the nature of the object, you just declare the guarantees of that interface.
So when you define your IMenuModel interface and apply it to your imported object you are saying: "I know and I can guarantee that the given object provides the members defined in the interface." This guarantee is satisfied by your object, so everything is fine there. The object however is still transmitted and restored in its full glory. Consider the interfaces as minimum guarantees, not as full descriptions of the object.
If you don't want the additional members of the object, your only choice is to let the server send only the parts of the object you need. If you can't do that, you don't need to worry, as your object meets the minimum requirements of the interface. Just ignore the additional values.

Resources