Is it possible for someone to build an Apollo tutorial?

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…

  1. 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.
  2. 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.
  3. The conclusion has a blurb that reads “XXX if we deploy in time” A missing link, I guess?
1 Like

I’m currently writing a handbook about GraphQL, in Chinese, and translating to English in Async.

Here is what I think it should contain:

Basic:

  • Go through building steps: Modeling -> Schema -> resolver func -> setup server and client -> query data
  • Modeling: Types in Schema and Resolver
  • Progressive Data Fetching: Pagination, walking through relationships and TUI
  • Be like QQ!: Subscription, File Upload and more [RFD]
  • Caching: Server-Side and Client-Side
    Advanced:
  • Transition Period: Wrapping REST to GraphQL
  • Sealing: Cascading Gateways
  • Security: Hacking into GraphQL
  • Future: GraphQL Anywhere

Can you come up with some other topic that I should cover?

2 Likes

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.

+1

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.

Seems mutations have no way to cascade…

4 Likes

I’m using Neo4j and Apollo. I haven’t found a synergy between Neo4j and GraphQL that’s worth using Neo4j if it’s not a natural fit for your data.

That said, I love Neo4j!

Here’s what I’m doing. Feel free to criticize it as genius or moronic. :slight_smile:

My queries are in one folder (you can separate them into folders as needed), mutations in another.

// queries/vehiclesToDisplay.js

const query = gql`
    query VehiclesToDisplay {
        vehicles {
            id,
            vehicleId,
            Attributes {
                year
                make
                model
                boughtfrom
            }
        }
    }
`;
export default query;

// mutations/updateYear.js
const updateYear = gql`
    mutation changeYear($id: String!, $vehicleId: Int!, $year: Int!) {
        changeYear(id: $id, vehicleId: $vehicleId, year: $year) {
            year
        }
    }
`;
export default updateYear;

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.

2 Likes

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

1 Like

I’m confused - isn’t graphql already and HOC? You can use it with compose and everything.

[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.

1 Like

Great work @nmaro !

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 again for sharing!

meteor+apollo release date?

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) {}

Quick tip that could help someone.

I struggled with Apollo Client mutation updates. I’m using meteorClientConfig() with Mongo and Rethink.

meteorClientConfig looks for the Mongo _id. My Rethink database uses id. This solved my updating problems…

const meteor = meteorClientConfig();
meteor.dataIdFromObject = result => {
  if (result.id && result.__typename) {
    return result.__typename + result.id;
  }
 if (result._id && result.__typename) {
    return result.__typename + result._id;
  }
  return null;
};
const client = new ApolloClient(meteor);
1 Like

I think, it must to be here https://www.learnapollo.com

1 Like

Githunt using polymer as the view layer. https://github.com/aruntk/GitHunt-Polymer.

Built using polymer-apollo package https://github.com/aruntk/polymer-apollo.

1 Like

Yep, my beautiful beautiful postgres how I miss you.

I’m trying to right apps using highly relational data and MongoDB doesn’t lend itself towards that in the same way a relational database does.

I do really love Meteor though and would like to stick with it.

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.

It seems you can nest / cascade mutations:

After reading somewhere that:

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.

1 Like

Please update the Apollo tutorial for the latest version, in particular this page:
http://dev.apollodata.com/tools/graphql-tools/guide.html
and

A tutorial should use the latest version, not an old version with instructions to later migrate to a newer version.

1 Like