-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Root Fields w/o Node Mapping #112
Comments
@yungsters @josephsavona is it possible that this change would also allow us to remove the Relay-specific Input Objects on mutations? It seems super strange that GraphQL supports multiple arguments but then Relay forces them to all be wrapped up ;-) Edit: would lose the ability to have a single variable in the document and stuff all the values into a variable as an input object though. |
Do you have any example code as to how the |
@vincentriemer take a look at the todo app's schema for an example of setting up a root |
This really confused me. This limitation should be spelled out more clearly in the docs and in relay-starter-kit. There is already a root object: the In the starter kit, the root object is I think the starter kit should change the Btw, I really wanted to create a connection type at the root level. Requiring two levels of As for making things continue to work at Facebook, I don't know the specifics, but it seems like removing this restriction shouldn't negatively impact anything, right? You'd just need to make Relay's parser smart enough to parse queries that don't fall under this restriction. If you wanted to keep the restriction internally, you could write some sort of validation process to check if anyone is violating the restriction before submitting their code. |
Thanks for this, @nickretallack. Right now, I'm working on literally nothing else but enabling identifying/non-identifying singular/plural fields at the root, including connections. Hold tight! |
@josephsavona I am aware of the plural identifying root field, but I have two issues there
|
So, with the fragment on Viewer {
root {
node(id: $whatever) {
...
}
} But doing that gives me:
|
@LegNeato The |
I have it there but still not getting how to query it from client code as the client fragments all refer to const queryType = new GraphQLObjectType({
name: 'Query',
fields: () => ({
node: nodeField,
viewer: {
type: viewerType,
},
}),
}); I'll poke at it some more and take it to stackoverflow if I still don't get it. |
@LegNeato I used to have my own copy of node called However, have you considered (I am doing this now instead myself) just using two root queries:
|
I ended up figuring it out, or at least something that works nicely. @miracle2k I think I can't just blindly use In the schema definition: // This is top-level / "root" node.
const queryType = new GraphQLObjectType({
name: 'Query',
fields: () => ({
// The node query lets us query for any object with an id w/o having to manually define
// queries under the viewer "global node".
node: nodeField,
// This is the "global node" workaround mentioned above.
viewer: {
type: viewerType,
},
}),
});
export const Schema = new GraphQLSchema({
query: queryType,
}); In the // This means when BarComponent is rendered, it will
// do a node query with the barID from the URL and query the node fields defined in
// the BarComponent component fragment named "node".
<Route path=":fooID/edit/:barID" component={BarComponent} queries={{
viewer: () => Relay.QL`query { viewer }`,
node: () => Relay.QL`query { node(id: $barID) }`,
}} /> In the client component: export default Relay.createContainer(BarComponent, {
fragments: {
// Define what we need to query from the viewer "global node".
viewer: () => Relay.QL`
fragment on Viewer {
// Whatever fields...
}
`,
// Define what we need to query from the node.
node: () => Relay.QL`
fragment on Node {
id,
... on Bar {
// Whatever fields...
}
},
`,
},
}); |
We're preparing Relay 2, which completely removes the restrictions and special casing around root fields. So I'm going to close this as we're unlikely to take any direct action on it, but people using Relay 1 will still be able to find this issue via search. Thanks to everybody who has participated in the thread! |
@maletor That extra level of indirection isn't necessary. It's sufficient to do:
|
@wincent I ran into an issue recently where Problematic code: {
query: graphql`
fragment RelaySelectComponent_query on Query
@argumentDefinitions(s: { type: "String", defaultValue: "beer" }) {
products(search: $s) {
edges {
node {
id
gtin
description
}
}
}
}
`
},
graphql`
# Refetch query to be fetched upon calling refetch.
# Notice that we re-use our fragment and the shape of this query matches our fragment spec. $count: Int,
query RelaySelectComponentRefetchQuery($s: String = "wine") {
...RelaySelectComponent_query @arguments(s: $s)
}
} I am not as experienced as one (i.e. me) would hope, so I can't make it into a definitive bug report, but I'm asking, respectfully, you guys take a look. I wasted good 20 work hours trying to find a solution. |
@yungsters maybe you can comment on this? |
This is working fine on Relay Modern |
@sibelius the code snippet above was tested last in Relay 1.4.1 and was failing. I might be mistaken of course. |
|
Thanks for the help and efforts, please remove all api's and reset my accounts and balance to zero (0). Since, I was bugged or hacked. |
Problem
Relay currently only knows how to handle these three types of root fields:
empire
queries{id: "123", ...}
ship(id: "456")
queries{id: "456", ...}
ships(ids: ["456", "789"])
queries[{id: "456", ...}, {id: "789", ...}]
However, it has become clear that Relay needs to support any kind of root field. For example:
Workaround
For now, the unsupported use cases can be implemented by creating a "global node", commonly called the
viewer
. You can then add arbitrary fields toviewer
.Rationale
Historically, GraphQL (as used internally at Facebook) did not have a root type or root fields. Instead, it had special "root calls" such as
node
,nodes
,me
, andusernames
. Much of Relay was built on top of this assumption that the "root calls" return nodes.For example, when we fetch
me
and get{id: "123", ...}
, we record the association between theme
root field and the node with ID of 123. Now, if we ever encounter another query forme
, we can check our store for the node with ID of 123 and resolve the query without having to potentially re-fetch all of the fields we already have forme
.Another example, when we fetch
nodes(ids: ["123", "456"])
, we record the association between each argument and their respective response nodes. This allows us to fulfill queries fornode(id: "123")
andnode(id: "456")
even though we may never have independently queried for either before. (We would also be able to fulfillme
if the association from above was established.)Next Steps
id
of the response. Currently all root arguments are assumed to be identifying.The text was updated successfully, but these errors were encountered: