Skip to content

Instantly share code, notes, and snippets.

@jackie1santana
Last active May 3, 2020 22:34
Show Gist options
  • Save jackie1santana/bc4c8be7c39477596683e296f5f9daed to your computer and use it in GitHub Desktop.
Save jackie1santana/bc4c8be7c39477596683e296f5f9daed to your computer and use it in GitHub Desktop.
Express-GraphQL/Apollo Client Set Up
const express = require('express')
const graphqlHTTP = require('express-graphql')
const schema = require('./schema/schema')
const app = express()
app.use('/graphql', graphqlHTTP({
schema,
graphiql: true
}))
app.listen(4000, () => {
console.log('server running on port 4000')
})
const graphql = require('graphql')
const { GraphQLObjectType, GraphQLString, GraphQLSchema } = graphql;
const books = [
{ name: 'Name of the Wind', genre: 'Fantasy', id: '1'},
{ name: 'The final Empire', genre: 'Fantasy', id: '2'},
{ name: 'The Long Earth', genre: 'Sci-Fi', id: '3'}
]
//defined your 1st object type for the schema
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLString},
name: { type: GraphQLString },
genre: { type: GraphQLString }
})
})
// put both Types above inside the root query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: {id: { type: GraphQLString }},
resolve(parent, args){
//code to get data from db/ or other source
//using Array.find() to return value
return books.find(i => i.id == args.id)
}
}
}
})
module.exports = new GraphQLSchema({
query:RootQuery
})
const graphql = require('graphql')
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema ,
GraphQLID,
GraphQLInt,
GraphQLList
} = graphql;
const books = [
{ name: 'Name of the Wind', genre: 'Fantasy', id: '1', authorId: '1'},
{ name: 'The final Empire', genre: 'Fantasy', id: '2', authorId: '2'},
{ name: 'The Long Earth', genre: 'Sci-Fi', id: '3', authorId: '3'},
{ name: 'The Hero of Ages', genre: 'Fantasy', id: '4', authorId: '2' },
{ name: 'The Colour of Magic', genre: 'Fantasy', id: '5', authorId: '3' },
{ name: 'The Light Fantastic', genre: 'Fantasy', id: '6', authorId: '3' }
]
const authors = [
{ name: 'Patrick Rothfuss', age: 44, id: '1'},
{ name: 'Brandon Sanderson', age: 42, id: '2'},
{ name: 'Terry Pratchett', age: 66, id: '3'}
]
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: GraphQLList(BookType),
resolve(parent, args){
console.log(parent)
return books.filter(i => i.authorId == parent.id)
}
}
})
})
//defined your 1st object type for the schema
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author:{
type: AuthorType,
resolve(parent, args){
console.log(parent)
return authors.find(i => i.id == parent.authorId)
}
}
})
})
// put both Types above inside the root query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: {id: { type: GraphQLID }},
resolve(parent, args){
//code to get data from db/ or other source
//using lodash
// return _.find(books, {id: args.id })
return books.find(i => i.id == args.id)
}
},
author: {
type: AuthorType,
args: {id: {type: GraphQLID}},
resolve(parent, args){
console.log(parent)
return authors.find(i => i.id == args.id)
}
},
books: {
type: new GraphQLList(BookType),
resolve(parent, args){
return books
}
},
authors: {
type: new GraphQLList(AuthorType),
resolve(parent, args){
return authors
}
},
}
})
module.exports = new GraphQLSchema({
query:RootQuery
})
const graphql = require('graphql')
const Book = require('../models/book')
const Author = require('../models/author')
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema ,
GraphQLID,
GraphQLInt,
GraphQLList
} = graphql;
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: GraphQLList(BookType),
resolve(parent, args){
// console.log(parent)
// return books.filter(i => i.authorId == parent.id)
}
}
})
})
//defined your 1st object type for the schema
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author:{
type: AuthorType,
resolve(parent, args){
// console.log(parent)
// return authors.find(i => i.id == parent.authorId)
}
}
})
})
// put both Types above inside the root query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: {id: { type: GraphQLID }},
resolve(parent, args){
//code to get data from db/ or other source
//using lodash
// return _.find(books, {id: args.id })
// return books.find(i => i.id == args.id)
}
},
author: {
type: AuthorType,
args: {id: {type: GraphQLID}},
resolve(parent, args){
// console.log(parent)
// return authors.find(i => i.id == args.id)
}
},
books: {
type: new GraphQLList(BookType),
resolve(parent, args){
// return books
}
},
authors: {
type: new GraphQLList(AuthorType),
resolve(parent, args){
// return authors
}
},
}
})
//redefine types
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt }
},
resolve(parent, args){
//author model from mongoose schema
let author = new Author({
name: args.name,
age: args.age
})
return author.save()
}
},
addBook: {
type: BookType,
args: {
name: { type: GraphQLString },
genre: { type: GraphQLString },
authorId: { type: GraphQLID }
},
resolve(parent, args){
//author model from mongoose schema
let book = new Book({
name: args.name,
genre: args.genre,
authorId: args.authorId
})
return book.save()
}
},
}
})
module.exports = new GraphQLSchema({
query:RootQuery,
mutation: Mutation
})
import { gql } from 'apollo-boost'
//pulling from the graphql uri
const getBooksQuery = gql`
{
books {
name
id
}
}
`
//pulling from the graphql uri
const getAuthorsQuery = gql`
{
authors {
name
id
}
}
`
const addBookMutation = gql`
mutation($name: String!, $genre: String!, $authorId: ID!) {
addBook(name: $name, genre: $genre, authorId: $authorId){
name
id
}
}
`
//making query from user
const getBookQuery = gql`
query($id: String){
book(id: ID){
id
name
genre
author{
id
name
age
books{
name
id
}
}
}
}
`
export { getAuthorsQuery, getBooksQuery, addBookMutation, getBookQuery }
app.js (pass in query varables into mutations function via state)
import React, { Component } from 'react'
import { graphql} from 'react-apollo'
import { getAuthorsQuery, addBookMutation } from '../queries/queries'
import { flowRight as compose } from 'lodash'
//form tag
class AddBook extends Component {
constructor(props){
super(props)
this.state = {
name: '',
genre: '',
authorId: ''
}
}
displayAuthors(){
const data = this.props.getAuthorsQuery
if(data.loading){
return (<option disabled>Loading Authors..</option>)
}else {
return data.authors.map(author => {
return (<option key={author.id} value={author.id} >{author.name}</option>)
})
}
}
submitForm(e){
e.preventDefault()
this.props.addBookMutation({
variables: {
name: this.state.name,
genre: this.state.genre,
authorId: this.state.authorId
}
})
}
render() {
console.log(this.props)
return (
<form id="add-book" onSubmit={this.submitForm.bind(this)} >
<div className="field" >
<label>Book Name:</label>
<input type="text" onChange={(e) => this.setState({ name: e.target.value })} />
</div>
<div className="field" >
<label>Genre:</label>
<input type="text" onChange={(e) => this.setState({ genre: e.target.value })}/>
</div>
<div className="field" >
<label>Author:</label>
<select onChange={(e) => this.setState({ authorId: e.target.value })}>
<option>Select author:</option>
{ this.displayAuthors() }
</select>
</div>
<button>+</button>
</form>
)
}
}
//this basically says, take graphql and bind geyBooks Query to BookList
export default compose(
//use compose to bind queries to client & bind mutations to client
graphql(getAuthorsQuery, {name: "getAuthorsQuery"}),
graphql(addBookMutation, {name: "addBookMutation"})
//both query & mutations are now bound to (addBook)
)(AddBook);
//use compose to bind multiple queries
import React, { Component } from 'react'
import { gql } from 'apollo-boost'
import { graphql } from 'react-apollo'
//pulling from the graphql uri
const getBooksQuery = gql `
{
books {
name,
id
}
}
`
//now we need to bind this query to this component (react-apollo package does that)
class BookList extends Component {
displayBooks(){
const data = this.props.data;
if(data.loading){
return (<div>Loading Books...</div>)
}else {
return data.books.map(book => {
return (
<li>{book.name}</li>
)
})
}
}
render() {
console.log(this.props)
return (
<div>
<ul id="book-list" >
{ this.displayBooks() }
</ul>
</div>
)
}
}
//this basically says, take graphql and bind geyBooks Query to BookList
export default graphql(getBooksQuery)(BookList);
const graphql = require('graphql')
const Book = require('../models/book')
const Author = require('../models/author')
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema ,
GraphQLID,
GraphQLInt,
GraphQLList
} = graphql;
//defined your 1st object type for the schema
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author:{
type: AuthorType,
resolve(parent, args){
// console.log(parent)
// return authors.find(i => i.id == parent.authorId)
return Author.findById(parent.authorId)
}
}
})
})
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType),
resolve(parent, args){
// console.log(parent)
// return books.filter(i => i.authorId == parent.id)
return Book.find({ authorId: parent.id})
}
}
})
})
// put both Types above inside the root query
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: {id: { type: GraphQLID }},
resolve(parent, args){
//code to get data from db/ or other source
//using lodash
// return _.find(books, {id: args.id })
// return books.find(i => i.id == args.id)
return Book.findById(args.id)
}
},
author: {
type: AuthorType,
args: {id: {type: GraphQLID}},
resolve(parent, args){
// console.log(parent)
// return authors.find(i => i.id == args.id)
return Author.findById(args.id)
}
},
books: {
type: new GraphQLList(BookType),
resolve(parent, args){
// return books
return Book.find({})
}
},
authors: {
type: new GraphQLList(AuthorType),
resolve(parent, args){
// return authors
return Author.find({})
}
},
}
})
//redefine types
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt }
},
resolve(parent, args){
//author model from mongoose schema
let author = new Author({
name: args.name,
age: args.age
})
return author.save()
}
},
addBook: {
type: BookType,
args: {
name: { type: GraphQLString },
genre: { type: GraphQLString },
authorId: { type: GraphQLID }
},
resolve(parent, args){
//author model from mongoose schema
let book = new Book({
name: args.name,
genre: args.genre,
authorId: args.authorId
})
return book.save()
}
},
}
})
module.exports = new GraphQLSchema({
query:RootQuery,
mutation: Mutation
})
submitForm(e){
e.preventDefault()
this.props.addBookMutation({
variables: {
name: this.state.name,
genre: this.state.genre,
authorId: this.state.authorId
},
refetchQueries: [{ query: getBooksQuery }]
})
import React from 'react';
import BookList from './components/BookList'
import AddBook from './components/AddBook'
import ApolloClient from 'apollo-boost'
import { ApolloProvider } from 'react-apollo'
//Apollo client set up
const client = new ApolloClient({
uri: '/graphql'
})
function App() {
return (
<ApolloProvider client={client}>
<div id="main">
<h1>Jackie's Reading List</h1>
<BookList/>
<AddBook/>
</div>
</ApolloProvider>
);
}
export default App;
app.js
render() {
console.log(this.props)
return (
<div>
<ul id="book-list" >
{ this.displayBooks() }
</ul>
<BookDetails bookId={this.state.selected} />
</div>
)
query.js
const getBookQuery = gql`
query($id: String){
book(id: ID){
id
name
genre
author{
id
name
age
books{
name
id
}
}
}
}
`
book details.jjs
//this basically says, take graphql and bind geyBooks Query to BookList
export default graphql(getBookQuery, {
options: (props) => {
return {
variables: {
id: props.bookId
}
}
}
})(BookDetails);
@jackie1santana
Copy link
Author

If you are having rendering issues after implementing a mutation & the mutation is not re rendering immediately use refetchQueries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment