mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
sample apps(update): update gatsby sample app (#2969)
This commit is contained in:
parent
e43be51dc6
commit
040b069d62
@ -8,89 +8,210 @@ Boilerplate to get started with Gatsby, Hasura GraphQL engine as CMS and postgre
|
||||
|
||||
# Tutorial
|
||||
|
||||
- Deploy Postgres and GraphQL Engine on Heroku:
|
||||
|
||||
[![Deploy to
|
||||
heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/hasura/graphql-engine-heroku)
|
||||
- Get the Heroku app URL (say `my-app.herokuapp.com`)
|
||||
- Clone this repo:
|
||||
```bash
|
||||
git clone https://github.com/hasura/graphql-engine
|
||||
cd graphql-engine/community/sample-apps/gatsby-postgres-graphql
|
||||
```
|
||||
1. Deploy Postgres and GraphQL Engine on Heroku:
|
||||
|
||||
- Create `author` table:
|
||||
|
||||
Open Hasura console: visit https://my-app.herokuapp.com on a browser
|
||||
Navigate to `Data` section in the top nav bar and create a table as follows:
|
||||
[![Deploy to
|
||||
heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/hasura/graphql-engine-heroku)
|
||||
|
||||
![Create author table](./assets/add_table.jpg)
|
||||
2. Get the Heroku app URL (say `my-app.herokuapp.com`)
|
||||
3. Clone this repo:
|
||||
|
||||
- Insert sample data into `author` table:
|
||||
```bash
|
||||
git clone https://github.com/hasura/graphql-engine
|
||||
cd graphql-engine/community/sample-apps/gatsby-postgres-graphql
|
||||
```
|
||||
|
||||
![Insert data into author table](./assets/insert_data.jpg)
|
||||
4. Create `author` table:
|
||||
|
||||
Verify if the row is inserted successfully
|
||||
Open Hasura console: visit https://my-app.herokuapp.com on a browser
|
||||
Navigate to `Data` section in the top nav bar and create a table as follows:
|
||||
|
||||
![Insert data into author table](./assets/browse_rows.jpg)
|
||||
![Create author table](./assets/add_table.jpg)
|
||||
|
||||
- Install npm modules:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
5. Insert sample data into `author` table:
|
||||
|
||||
- Configure gatsby to use `gatsby-source-graphql` plugin and a connection GraphQL url to stitch the schema.
|
||||
![Insert data into author table](./assets/insert_data.jpg)
|
||||
|
||||
Verify if the row is inserted successfully
|
||||
|
||||
![Insert data into author table](./assets/browse_rows.jpg)
|
||||
|
||||
6. Install npm modules:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
7. Configure gatsby to use `gatsby-source-graphql` plugin and a connection GraphQL url to stitch the schema.
|
||||
|
||||
```js
|
||||
{
|
||||
plugins: [
|
||||
{
|
||||
resolve: 'gatsby-source-graphql', // <- Configure plugin
|
||||
resolve: "gatsby-source-graphql", // <- Configure plugin
|
||||
options: {
|
||||
typeName: 'HASURA',
|
||||
fieldName: 'hasura', // <- fieldName under which schema will be stitched
|
||||
typeName: "HASURA",
|
||||
fieldName: "hasura", // <- fieldName under which schema will be stitched
|
||||
createLink: () =>
|
||||
createHttpLink({
|
||||
uri: `${ process.env.HASURA_GRAPHQL_URL }`, // <- Configure connection GraphQL url
|
||||
uri: `${process.env.GATSBY_HASURA_GRAPHQL_URL}`, // <- Configure connection GraphQL url
|
||||
headers: {},
|
||||
fetch,
|
||||
fetch
|
||||
}),
|
||||
refetchInterval: 10, // Refresh every 10 seconds for new data
|
||||
},
|
||||
},
|
||||
]
|
||||
refetchInterval: 10 // Refresh every 10 seconds for new data
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
- Make a GraphQL query from your component
|
||||
8. Run the app:
|
||||
|
||||
```bash
|
||||
GATSBY_HASURA_GRAPHQL_URL=https://my-app.herokuapp.com/v1/graphql npm run develop
|
||||
```
|
||||
|
||||
9. Test the app
|
||||
Visit [http://localhost:8000](http://localhost:8000) to view the app
|
||||
|
||||
![Demo app](./assets/test_app.jpg)
|
||||
|
||||
# Make a GraphQL query from your component using hooks
|
||||
|
||||
1. Create a component named `AuthorList.js`:
|
||||
|
||||
```js
|
||||
const Index = ({ data }) => (
|
||||
<div>
|
||||
<h1>My Authors </h1>
|
||||
<AuthorList authors={data.hasura.author} />
|
||||
</div>
|
||||
)
|
||||
export const query = graphql`
|
||||
query AuthorQuery {
|
||||
hasura { # <- fieldName as configured in the gatsby-config
|
||||
author { # Normal GraphQL query
|
||||
import React from "react";
|
||||
import { useQuery } from "@apollo/react-hooks";
|
||||
import { gql } from "apollo-boost";
|
||||
|
||||
const GET_AUTHORS = gql`
|
||||
query {
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const AuthorList = () => {
|
||||
const { loading, error, data } = useQuery(GET_AUTHORS);
|
||||
|
||||
if (loading) return "loading...";
|
||||
if (error) return `error: ${error.message}`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{data.author.map((author, index) => (
|
||||
<div key={index}>
|
||||
<h2>{author.name}</h2>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthorList;
|
||||
export { GET_AUTHORS };
|
||||
```
|
||||
|
||||
# Make a GraphQL mutation using hooks
|
||||
|
||||
Additional packages are needed to be added to support mutations: <br/>
|
||||
`npm install @apollo/react-hooks apollo-boost isomorphic-fetch`
|
||||
|
||||
1. Create an `apollo.js` util file:
|
||||
|
||||
```js
|
||||
import ApolloClient from "apollo-boost";
|
||||
import fetch from "isomorphic-fetch";
|
||||
|
||||
export const client = new ApolloClient({
|
||||
uri: process.env.GATSBY_HASURA_GRAPHQL_URL,
|
||||
fetch
|
||||
});
|
||||
```
|
||||
|
||||
2. Create `gatsby-browser.js` and `gatsby-ssr.js`
|
||||
|
||||
```js
|
||||
import React from "react";
|
||||
import { ApolloProvider } from "@apollo/react-hooks";
|
||||
import { client } from "./src/utils/apollo";
|
||||
|
||||
export const wrapRootElement = ({ element }) => (
|
||||
<ApolloProvider client={client}>{element}</ApolloProvider>
|
||||
);
|
||||
```
|
||||
|
||||
3. Create an `AddAuthor.js` component to add mutations:
|
||||
|
||||
```js
|
||||
import React, { useState } from "react";
|
||||
import { useMutation } from "@apollo/react-hooks";
|
||||
import { gql } from "apollo-boost";
|
||||
import { GET_AUTHORS } from "./AuthorList";
|
||||
|
||||
const ADD_AUTHOR = gql`
|
||||
mutation insert_author($name: String!) {
|
||||
insert_author(objects: { name: $name }) {
|
||||
returning {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
`;
|
||||
|
||||
const AddAuthor = () => {
|
||||
const [author, setAuthor] = useState("");
|
||||
const [insert_author, { loading, error }] = useMutation(ADD_AUTHOR, {
|
||||
update: (cache, { data }) => {
|
||||
setAuthor("");
|
||||
const existingAuthors = cache.readQuery({
|
||||
query: GET_AUTHORS
|
||||
});
|
||||
|
||||
// Add the new author to the cache
|
||||
const newAuthor = data.insert_author.returning[0];
|
||||
cache.writeQuery({
|
||||
query: GET_AUTHORS,
|
||||
data: {author: [newAuthor, ...existingAuthors.author]}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (loading) return "loading...";
|
||||
if (error) return `error: ${error.message}`;
|
||||
|
||||
const handleSubmit = event => {
|
||||
event.preventDefault();
|
||||
insert_author({
|
||||
variables: {
|
||||
name: author
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<label htmlFor="author">
|
||||
Add Author:
|
||||
<input
|
||||
name="author"
|
||||
value={author}
|
||||
onChange={event => setAuthor(event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<button type="submit">ADD</button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddAuthor;
|
||||
```
|
||||
|
||||
- Run the app:
|
||||
```bash
|
||||
HASURA_GRAPHQL_URL=https://my-app.herokuapp.com/v1/graphql npm run develop
|
||||
```
|
||||
- Test the app
|
||||
Visit [http://localhost:8000](http://localhost:8000) to view the app
|
||||
|
||||
![Demo app](./assets/test_app.jpg)
|
||||
4. Run the app and test mutation. New data will be added to the top via a cache update.
|
||||
|
||||
# Contributing
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 46 KiB |
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
import { ApolloProvider } from "@apollo/react-hooks";
|
||||
import { client } from "./src/utils/apollo";
|
||||
|
||||
export const wrapRootElement = ({ element }) => (
|
||||
<ApolloProvider client={client}>{element}</ApolloProvider>
|
||||
);
|
@ -1,21 +1,22 @@
|
||||
const fetch = require(`node-fetch`)
|
||||
const { createHttpLink } = require(`apollo-link-http`)
|
||||
const fetch = require(`node-fetch`);
|
||||
const { createHttpLink } = require(`apollo-link-http`);
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
{
|
||||
resolve: 'gatsby-source-graphql',
|
||||
resolve: "gatsby-source-graphql",
|
||||
options: {
|
||||
typeName: 'HASURA',
|
||||
fieldName: 'hasura',
|
||||
createLink: () =>
|
||||
createHttpLink({
|
||||
uri: `${ process.env.HASURA_GRAPHQL_URL }`,
|
||||
typeName: "HASURA",
|
||||
fieldName: "hasura",
|
||||
createLink: () => {
|
||||
return createHttpLink({
|
||||
uri: process.env.GATSBY_HASURA_GRAPHQL_URL,
|
||||
headers: {},
|
||||
fetch,
|
||||
}),
|
||||
refetchInterval: 10, // Refresh every 60 seconds for new data
|
||||
},
|
||||
},
|
||||
fetch
|
||||
});
|
||||
},
|
||||
refetchInterval: 10 // Refresh every 60 seconds for new data
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
import { ApolloProvider } from "@apollo/react-hooks";
|
||||
import { client } from "./src/utils/apollo";
|
||||
|
||||
export const wrapRootElement = ({ element }) => (
|
||||
<ApolloProvider client={client}>{element}</ApolloProvider>
|
||||
);
|
@ -8,11 +8,15 @@
|
||||
"serve": "gatsby serve"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hot-loader/react-dom": "^16.8.6",
|
||||
"@apollo/react-hooks": "^3.1.1",
|
||||
"apollo-boost": "^0.4.4",
|
||||
"apollo-link-http": "^1.5.5",
|
||||
"gatsby": "^2.0.9",
|
||||
"gatsby-link": "^2.0.2",
|
||||
"gatsby-source-graphql": "^2.0.2",
|
||||
"react": "^16.5.2",
|
||||
"react-dom": "^16.5.2"
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"react": "^16.9",
|
||||
"react-dom": "^16.9"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
import React, { useState } from "react";
|
||||
import { useMutation } from "@apollo/react-hooks";
|
||||
import { gql } from "apollo-boost";
|
||||
import { GET_AUTHORS } from "./AuthorList";
|
||||
|
||||
const ADD_AUTHOR = gql`
|
||||
mutation insert_author($name: String!) {
|
||||
insert_author(objects: { name: $name }) {
|
||||
returning {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const AddAuthor = () => {
|
||||
const [author, setAuthor] = useState("");
|
||||
const [insert_author, { loading, error }] = useMutation(ADD_AUTHOR, {
|
||||
update: (cache, { data }) => {
|
||||
setAuthor("");
|
||||
const existingAuthors = cache.readQuery({
|
||||
query: GET_AUTHORS
|
||||
});
|
||||
|
||||
// Add the new author to the cache
|
||||
const newAuthor = data.insert_author.returning[0];
|
||||
cache.writeQuery({
|
||||
query: GET_AUTHORS,
|
||||
data: {author: [newAuthor, ...existingAuthors.author]}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (loading) return "loading...";
|
||||
if (error) return `error: ${error.message}`;
|
||||
|
||||
const handleSubmit = event => {
|
||||
event.preventDefault();
|
||||
insert_author({
|
||||
variables: {
|
||||
name: author
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<label htmlFor="author">
|
||||
Add Author:
|
||||
<input
|
||||
name="author"
|
||||
value={author}
|
||||
onChange={event => setAuthor(event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<button type="submit">ADD</button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddAuthor;
|
@ -1,13 +1,32 @@
|
||||
import React from "react"
|
||||
import React from "react";
|
||||
import { useQuery } from "@apollo/react-hooks";
|
||||
import { gql } from "apollo-boost";
|
||||
|
||||
const AuthorList = ({ authors }) => (
|
||||
<div>
|
||||
{authors.map((a, i) => (
|
||||
<div key={i}>
|
||||
<h2>{a.name}</h2>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
const GET_AUTHORS = gql`
|
||||
query {
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const AuthorList = () => {
|
||||
const { loading, error, data } = useQuery(GET_AUTHORS);
|
||||
|
||||
if (loading) return "loading...";
|
||||
if (error) return `error: ${error.message}`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{data.author.map((author, index) => (
|
||||
<div key={index}>
|
||||
<h2>{author.name}</h2>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthorList;
|
||||
export { GET_AUTHORS };
|
||||
|
@ -1,22 +1,14 @@
|
||||
import React from "react"
|
||||
import AuthorList from "../components/AuthorList"
|
||||
import React from "react";
|
||||
|
||||
const Index = ({ data }) => (
|
||||
import AddAuthor from "../components/AddAuthor";
|
||||
import AuthorList from "../components/AuthorList";
|
||||
|
||||
const Index = () => (
|
||||
<div>
|
||||
<h1>My Authors </h1>
|
||||
<AuthorList authors={data.hasura.author} />
|
||||
<h1>My Authors</h1>
|
||||
<AddAuthor />
|
||||
<AuthorList />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
export default Index;
|
||||
|
||||
export const query = graphql`
|
||||
query AuthorQuery {
|
||||
hasura {
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
export default Index;
|
@ -0,0 +1,7 @@
|
||||
import ApolloClient from "apollo-boost";
|
||||
import fetch from "isomorphic-fetch";
|
||||
|
||||
export const client = new ApolloClient({
|
||||
uri: process.env.GATSBY_HASURA_GRAPHQL_URL,
|
||||
fetch
|
||||
});
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user