What The Hell
is graphql
Ramsay Lanier
In a nutshell, graphql
is a query language for your api
in fact, graphql is a replacement for rest
Benefits over rest:
Inherently self documenting
More efficient (less server round trips)
Better developer tools
Easier to secure
The graphql architecture
source: https://kadira.io
GraphQL Queries
The shape of the resulting data is the exact same shape as our query.
Same thing, but with variables and a named query
You can even give your data fields Aliases.
GraphQL Type Language
type Post {
id: Int
post_title: String
post_content: String
post_excerpt: String
post_status: String
post_type: String
post_name: String
post_parent: Int
menu_order: Int
layout: Postmeta
thumbnail: String
}
type Postmeta {
id: Int
meta_id: Int
post_id: Int
meta_key: String
meta_value: String
}
type Menu {
id: ID!
name: String
items: [MenuItem]
}
type MenuItem {
id: ID!
post_title: String
linkedId: Int
object_type: String
order: Int
navitem: Post
children: [MenuItem]
}
type Query {
posts(post_type: String = "post", limit: Int, skip: Int): [Post]
menus(name: String): Menu
post(name: String, id: Int): Post
}
schema {
query: Query
}
Lastly, you need a Query type which serves as the root query. You then need a schema which contains the root query.
type Menu {
id: ID!
name: String
items: [MenuItem]
}
type MenuItem {
id: ID!
post_title: String
linkedId: Int
object_type: String
order: Int
navitem: Post
children: [MenuItem]
}
type Post {
id: Int
post_title: String
post_content: String
post_excerpt: String
post_status: String
post_type: String
post_name: String
post_parent: Int
menu_order: Int
thumbnail: String
}
type Query {
posts(post_type: String = "post", limit: Int, skip: Int): [Post]
menus(name: String): Menu
post(name: String, id: Int): Post
}
schema {
query: Query
}
GraphQL Resolvers
const Resolvers = {
Query: {
posts(_, args) {
return GetPosts(args);
},
menus(_, {name}) {
return GetMenu(name);
},
post(_, {name, id}) {
if (name) {
return GetPostByName(name, id);
}
return GetPostById(id);
}
},
// more stuff here
...
};
type Query {
posts(post_type: String = "post", limit: Int, skip: Int): [Post]
menus(name: String): Menu
post(name: String, id: Int): Post
}
schema {
query: Query
}
getPosts({ post_type, limit = 10, skip = 0 }) {
return Post.findAll({
where: {
post_type,
post_status: 'publish'
},
limit: limit,
offset: skip
});
}
Putting it together with apollostack
Apollo is an incrementally-adoptable data stack that manages the flow of data between clients and backends.
Based on GraphQL, it gives you a principled, unified, and scalable API for developing modern apps on top of services.
Apollo server
import express from 'express';
import bodyParser from 'body-parser';
import { apolloExpress, graphiqlExpress } from 'apollo-server';
import { makeExecutableSchema } from 'graphql-tools';
import { Definitions, Resolvers } from './schema/schema';
const APP_PORT = 3000;
const app = express();
const executableSchema = makeExecutableSchema({
typeDefs: Definitions,
resolvers: Resolvers
});
app.use('/graphql', bodyParser.json(), apolloExpress({
schema: executableSchema,
context: {}
}));
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}));
app.listen(APP_PORT, () => console.log(
`GraphQL Server is now running on http://localhost:${APP_PORT}`
));
{
"query": "query getPost{ post(name: $postName) }",
"operationName": "getPost",
"variables": { "postName": "homepage" }
}
Apollo Server accepts only JSON-encoded POST requests. A valid request must contain either a query or an operationName(or both, in case of a named query), and may include variables. For example:
Apollo Client
IN REACT
import React from 'react';
import { render } from 'react-dom';
import { ApolloProvider } from 'react-apollo';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import ApolloClient from 'apollo-client';
// By default, this client will send queries to the
// `/graphql` endpoint on the same host
const client = new ApolloClient();
render(
<ApolloProvider client={client} store={store}>
<Router history={browserHistory} routes={routes}></Router>
</ApolloProvider>,
document.getElementById('root')
)
IN REACT
import React from 'react';
import Page from '../pages/page.js';
import PostContent from '../posts/PostContent';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag'
class FrontPageLayout extends React.Component{
render(){
const { loading } = this.props.data;
if (loading){
return (
<div>Loading...</div>
)
} else {
const { post_title, post_content, thumbnail} = data.page;
return (
<div styleName="content">
<div styleName="wrapper tight">
<h1 styleName="title">{post_title}</h1>
<PostContent post_content={post_content}/>
</div>
</div>
)
}
}
}
const GetPage = gql`
query getPage{
page(post_name: "homepage"){
id,
post_title,
post_content,
thumbnail
}
}
`;
const FrontPageWithData = graphql(GetPage)(FrontPageLayout);
export default FrontPageWithData;
What the hell is Graph QL
By Ramsay Lanier
What the hell is Graph QL
- 1,857