The code tour is wonderful. This is the kind of thing I feel like I’ve been waiting for. Once I got to the part about contexts, I was in completely uncharted territory. I’d never had this level of understanding before. I’d looked at resolvers before, but never gotten far enough to get what was happening. Everything past that was equally eye-opening.
Improvements that could be made…
The tour stops short of showing how data is stored to SQL which is also a pretty alien thing to me coming from a Meteor 1.0 mindset. Expanding the tour to cover how data is stored would be nice.
An introduction that explains what GitHunt is, what it is designed to do, would be an ideal start. I’ve seen the example referred to dozens of times, but I don’t actually know what it does.
The conclusion has a blurb that reads “XXX if we deploy in time” A missing link, I guess?
A topic I’m still struggling with is larger schema and query organization:
All info and tutorials talk about a basic app. But how do you handle larger projects? For example an app with several distinct sections( a user-info page, a comments section, a todo-section, and so on)
Do you create a long list of queries on the root?
Do you try to nest them? ( eg. root-query -> user -> account -> readingprefs )
what about mutations? All on the root mutation?
At the moment I’m trying the nested method, using some dummy queries as sections( like ‘users’). No idea if this is a valid way.
I’m also curious about this topic, I currently immigrant my knowledge about Neo4j modeling (a graph database) to GraphQL, I think they have something in common.
And I believe F8 app is in on a good path, worth a referring.
Then I use compose to put them together with the presentational component…
// vehicles.js
import UpdateYear from './mutations/updateYear';
import UpdateYear from './mutations/updateModel';
import VehiclesToDisplay from './queries/vehiclesToDisplay';
import Vehicle from './presentation/Vehicle';
import { graphql, compose } from 'react-apollo';
const options = {pollInterval: 5000};
export default compose(
graphql(query, options),
graphql(updateYear, { name: 'updateYear'}),
graphql(updateModel, { name: 'updateModel'})
)(Vehicle);
The Vehicle presentational component gets mutate and data.vehicles as a prop. To pass multiple mutations, set the name option, e.g. GqlHoc({ query: changeThis, {name: 'changeThis}), GqlHoc({ query: changeThat, {name: 'changeThat})
Known problems… the presentational component formats the mutation.
This looks pretty good to me. I really like the abstraction of queries/mutations, etc. I don’t have enough experience to know if this would be a problem for any reason.
I haven’t used recompose myself, but I would consider “recomposing” into a “container” component, as opposed to a “presentational” one to give yourself more flexibility in the future. For example, using fragments and then using graphql-anywhere to filter the query so you can displayVehiclesByYear, displayVehiclesByMake, etc
[quote=“sashko, post:57, topic:23416”]
I’m confused - isn’t graphql already and HOC? You can use it with compose and everything.
[/quote]I’m the one who’s confused. I thought that graphql had to invoke its second function. (I’m new to currying and still trying to wrap my head around it. I’ve gone into the Apollo source code, but I see it didn’t help me!)
After getting deeper into the docs, I see that I reinvented the wheel. Thank you for the correction. I updated my post.
I need to study about asyncand await to understand it better, but I think it is great material.
I spent a few hours trying to wrap my head around all the apollo/graphql-server repos and their relation. Your post confirmed the ideas I had and how I understood the way they relate.
Thanks! A little note regarding async/await: it’s best if you understand a bit of the history of dealing with asynchronous stuff in javascript.
The original approach was using callbacks: asynchMethod(function(err, res) { react here })
Then came promises promise = asyncMethod(); promise.then(function(res) {}).catch(function(err) {})
Then came async, which works with promises in the background: try { res = await asynchMethod() } catch(e) {}
Yeah good find! Our friends at Graphcool, a GraphQL backend as a service, produced this resource to teach people about Apollo Client. Just launched yesterday! It is a great resource to follow and they have an endpoint already set up for you, then after that you just need to learn how to set up a GraphQL API.
The only real difference between a mutation and a query is the word mutation. Interestingly, there is nothing stopping a query from including a side effect just like a mutation.
It made me think and try. And it turns out you can just as easily nest mutations.
Say you have an app with several distinct scenes. Your query could be something like:
schema {
query: Query
mutation: Mutation
}
type Query {
#parent query for scene 1
sceneOne: SceneOne
#parent query for scene 2
sceneTwo: SceneTwo
}
You can make the same kind of system for your mutations:
type Mutation {
sceneOne: SceneOne
}
Now, your sceneOne queries AND mutations both point to the same SceneOne type. Your SceneOne type could be defined as:
type SceneOne {
someSceneData: [ String ]
someOtherSceneData: [ Int ]
mutations: Mutations
}
someSceneData is a query for that particular scene, and mutations contains all your Mutations for that scene:
type Mutations {
setSomeSceneData( myVar: String!): Boolean
}
In this way, you have one GraphQL-tree where your mutations are nested side-by-side your queries. Another way could be to build 2 parallel trees ,one for queries, one for mutations.
I actually have no idea if it is a good idea to nest things like this or not, but to me it seems a lot more organized and structured.