mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
add react-static-graphql sample app (#1569)
This commit is contained in:
parent
9a6fa7fafc
commit
9c914f5637
3
community/sample-apps/react-static-graphql/.babelrc
Normal file
3
community/sample-apps/react-static-graphql/.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["react-static/babel-preset.js"]
|
||||
}
|
3
community/sample-apps/react-static-graphql/.eslintrc.js
Normal file
3
community/sample-apps/react-static-graphql/.eslintrc.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
extends: 'react-tools',
|
||||
}
|
9
community/sample-apps/react-static-graphql/.gitignore
vendored
Normal file
9
community/sample-apps/react-static-graphql/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
.next
|
||||
.cache
|
||||
dist
|
||||
.tempdist
|
||||
.DS_Store
|
||||
yarn-error.log
|
||||
.history
|
||||
tmp
|
117
community/sample-apps/react-static-graphql/README.md
Normal file
117
community/sample-apps/react-static-graphql/README.md
Normal file
@ -0,0 +1,117 @@
|
||||
# react-static-graphql
|
||||
|
||||
A sample app to get started with [react-static](https://github.com/nozzle/react-static) site generator, Hasura GraphQL engine and Postgres as database.
|
||||
|
||||
# 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)
|
||||
|
||||
Please checkout our [docs](https://docs.hasura.io/1.0/graphql/manual/deployment/index.html) for other deployment methods
|
||||
|
||||
- Get the Heroku app URL (say `my-app.herokuapp.com`)
|
||||
- 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:
|
||||
|
||||
![Create author table](../gatsby-postgres-graphql/assets/add_table.jpg)
|
||||
|
||||
- Insert sample data into `author` table:
|
||||
|
||||
![Insert data into author table](../gatsby-postgres-graphql/assets/insert_data.jpg)
|
||||
|
||||
Verify if the row is inserted successfully
|
||||
|
||||
![Insert data into author table](../gatsby-postgres-graphql/assets/browse_rows.jpg)
|
||||
|
||||
- Similarly, create an article table with the following data model:
|
||||
table: `article`
|
||||
columns: `id`, `title`, `content`, `author_id` (foreign key to `author` table's `id`) and `created_at`
|
||||
|
||||
![Create foreign key for author_id column to author's id](./assets/author_fk.png)
|
||||
|
||||
- Now create a relationship from article table to author table by going to the Relationships tab.
|
||||
|
||||
- Clone this repo:
|
||||
```bash
|
||||
git clone https://github.com/hasura/graphql-engine
|
||||
cd graphql-engine/community/sample-apps/react-static-graphql
|
||||
```
|
||||
|
||||
- Install npm modules:
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
- Open `src/apollo.js` and configure Hasura's GraphQL Endpoint as follows:
|
||||
```js
|
||||
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import fetch from 'node-fetch'
|
||||
|
||||
const client = new ApolloClient({
|
||||
link: new HttpLink({
|
||||
uri: 'https://myapp.herokuapp.com/v1alpha1/graphql',
|
||||
fetch
|
||||
}),
|
||||
cache: new InMemoryCache(),
|
||||
})
|
||||
|
||||
export default client
|
||||
|
||||
```
|
||||
Replace the `uri` argument with your Hasura GraphQL Endpoint.
|
||||
|
||||
- We have defined the graphql query in `src/graphql/queries/queries.js`.
|
||||
- GraphQL query to fetch author information
|
||||
|
||||
```graphql
|
||||
|
||||
query {
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
- GraphQL query to fetch articles written by author
|
||||
|
||||
```graphql
|
||||
|
||||
query($author: Int!) {
|
||||
article(where: {author_id: {_eq: $author}}) {
|
||||
id
|
||||
title
|
||||
content
|
||||
created_at
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
- In `pages/blog.js`, we do the templating for listing all the authors and in `containers/Post.js`, we do the templating for listing all the articles written by a selected author.
|
||||
|
||||
- Run the app:
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
- Test the app
|
||||
Visit [http://localhost:3000](http://localhost:3000) to view the app
|
||||
|
||||
- Bundle app
|
||||
```bash
|
||||
yarn stage
|
||||
```
|
||||
- Serve Production app
|
||||
```bash
|
||||
yarn serve
|
||||
```
|
||||
|
||||
For detailed explanation on how things work, checkout [react-static docs](https://github.com/nozzle/react-static).
|
BIN
community/sample-apps/react-static-graphql/assets/author_fk.png
Normal file
BIN
community/sample-apps/react-static-graphql/assets/author_fk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
32
community/sample-apps/react-static-graphql/package.json
Normal file
32
community/sample-apps/react-static-graphql/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "react-static-example-basic",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "react-static start",
|
||||
"stage": "react-static build --staging",
|
||||
"build": "react-static build",
|
||||
"bundle": "react-static bundle",
|
||||
"export": "react-static export",
|
||||
"serve": "serve dist -p 3000 -s"
|
||||
},
|
||||
"dependencies": {
|
||||
"@reach/router": "^1.2.1",
|
||||
"apollo-cache-inmemory": "^1.4.2",
|
||||
"apollo-client": "^2.4.12",
|
||||
"apollo-link-http": "^1.5.9",
|
||||
"axios": "^0.18.0",
|
||||
"babel-loader": "^8.0.5",
|
||||
"graphql": "^14.1.1",
|
||||
"graphql-tag": "^2.10.1",
|
||||
"node-fetch": "^2.3.0",
|
||||
"react": "^16.6.3",
|
||||
"react-apollo": "^2.4.1",
|
||||
"react-dom": "^16.6.3",
|
||||
"react-hot-loader": "^4.3.12",
|
||||
"react-static": "^6.0.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint-config-react-tools": "1.x.x",
|
||||
"serve": "10.1.1"
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
User-agent: *
|
27
community/sample-apps/react-static-graphql/src/App.js
vendored
Normal file
27
community/sample-apps/react-static-graphql/src/App.js
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react'
|
||||
import { Root, Routes } from 'react-static'
|
||||
import { Link } from '@reach/router'
|
||||
|
||||
import { ApolloProvider } from 'react-apollo'
|
||||
import client from './apollo'
|
||||
|
||||
import './app.css'
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<Root>
|
||||
<nav>
|
||||
<Link to="/">Home</Link>
|
||||
<Link to="/about">About</Link>
|
||||
<Link to="/blog">Blog</Link>
|
||||
</nav>
|
||||
<div className="content">
|
||||
<Routes />
|
||||
</div>
|
||||
</Root>
|
||||
</ApolloProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
14
community/sample-apps/react-static-graphql/src/apollo.js
vendored
Normal file
14
community/sample-apps/react-static-graphql/src/apollo.js
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import { ApolloClient } from 'apollo-client'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import fetch from 'node-fetch'
|
||||
|
||||
const client = new ApolloClient({
|
||||
link: new HttpLink({
|
||||
uri: 'http://localhost:8080/v1alpha1/graphql', // replace this with your own Hasura GraphQL Endpoint
|
||||
fetch
|
||||
}),
|
||||
cache: new InMemoryCache(),
|
||||
})
|
||||
|
||||
export default client
|
33
community/sample-apps/react-static-graphql/src/app.css
Normal file
33
community/sample-apps/react-static-graphql/src/app.css
Normal file
@ -0,0 +1,33 @@
|
||||
body {
|
||||
font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial,
|
||||
'Lucida Grande', sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #108db8;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 100%;
|
||||
background: #108db8;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 1rem;
|
||||
}
|
21
community/sample-apps/react-static-graphql/src/containers/Post.js
vendored
Normal file
21
community/sample-apps/react-static-graphql/src/containers/Post.js
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import { withRouteData } from 'react-static'
|
||||
import { Link } from '@reach/router'
|
||||
|
||||
export default withRouteData(({ articles }) => {
|
||||
const articlesList = articles.map((article, index) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<h3>{article.title}</h3>
|
||||
<p>{article.content}</p>
|
||||
</div>
|
||||
)}
|
||||
)
|
||||
return (
|
||||
<div>
|
||||
<Link to="/blog">{'<'} Back</Link>
|
||||
<br />
|
||||
{articlesList.length ? articlesList : 'There are no posts by this author'}
|
||||
</div>
|
||||
)}
|
||||
)
|
23
community/sample-apps/react-static-graphql/src/graphql/queries.js
vendored
Normal file
23
community/sample-apps/react-static-graphql/src/graphql/queries.js
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import gql from "graphql-tag";
|
||||
|
||||
const GET_AUTHOR = gql`
|
||||
query {
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const GET_ARTICLE = gql`
|
||||
query($author: Int!) {
|
||||
article(where: {author_id: {_eq: $author}}) {
|
||||
id
|
||||
title
|
||||
content
|
||||
created_at
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export { GET_ARTICLE, GET_AUTHOR };
|
27
community/sample-apps/react-static-graphql/src/index.js
vendored
Normal file
27
community/sample-apps/react-static-graphql/src/index.js
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
// Your top level component
|
||||
import App from './App'
|
||||
|
||||
// Export your top level component as JSX (for static rendering)
|
||||
export default App
|
||||
|
||||
// Render your app
|
||||
if (typeof document !== 'undefined') {
|
||||
const renderMethod = module.hot
|
||||
? ReactDOM.render
|
||||
: ReactDOM.hydrate || ReactDOM.render
|
||||
|
||||
const render = Comp => {
|
||||
renderMethod(<Comp />, document.getElementById('root'))
|
||||
}
|
||||
|
||||
// Render!
|
||||
render(App)
|
||||
|
||||
// Hot Module Replacement
|
||||
if (module.hot) {
|
||||
module.hot.accept('./App', () => render(require('./App').default))
|
||||
}
|
||||
}
|
7
community/sample-apps/react-static-graphql/src/pages/404.js
vendored
Normal file
7
community/sample-apps/react-static-graphql/src/pages/404.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<h1>404 - Oh no's! We couldn't find that page :(</h1>
|
||||
</div>
|
||||
)
|
7
community/sample-apps/react-static-graphql/src/pages/about.js
vendored
Normal file
7
community/sample-apps/react-static-graphql/src/pages/about.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<p>React Static is a progressive static site generator for React.</p>
|
||||
</div>
|
||||
)
|
23
community/sample-apps/react-static-graphql/src/pages/blog.js
vendored
Normal file
23
community/sample-apps/react-static-graphql/src/pages/blog.js
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react'
|
||||
import { withRouteData } from 'react-static'
|
||||
import { Link } from '@reach/router'
|
||||
|
||||
const Authors = ({ author }) => {
|
||||
const authorList = author.map((item) => {
|
||||
return (
|
||||
<div key={item.id}>
|
||||
<Link to={"/blog/" + item.id}>{item.name}</Link>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
{/* STATIC DATA FROM THE BUILD */}
|
||||
<h1>Authors</h1>
|
||||
{authorList.length ? authorList : 'There are no authors available'}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default withRouteData(Authors)
|
||||
|
9
community/sample-apps/react-static-graphql/src/pages/index.js
vendored
Normal file
9
community/sample-apps/react-static-graphql/src/pages/index.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
import { withSiteData } from 'react-static'
|
||||
|
||||
export default withSiteData(() => (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<h1>Welcome to React-Static</h1>
|
||||
<p>This demo integrates <a href="https://github.com/hasura/graphql-engine">Hasura GraphQL Engine</a> and allows you to generate static sites with your Postgres database using GraphQL</p>
|
||||
</div>
|
||||
))
|
39
community/sample-apps/react-static-graphql/static.config.js
Normal file
39
community/sample-apps/react-static-graphql/static.config.js
Normal file
@ -0,0 +1,39 @@
|
||||
import client from './src/apollo'
|
||||
import {GET_AUTHOR, GET_ARTICLE} from './src/graphql/queries'
|
||||
|
||||
export default {
|
||||
getSiteData: () => ({
|
||||
title: 'React Static with Hasura GraphQL',
|
||||
}),
|
||||
getRoutes: async () => {
|
||||
const {
|
||||
data: { author },
|
||||
} = await client.query({
|
||||
query: GET_AUTHOR,
|
||||
})
|
||||
return [
|
||||
{
|
||||
path: '/blog',
|
||||
getData: () => ({author}),
|
||||
children: author.map(item => ({
|
||||
path: `/${item.id.toString()}`,
|
||||
component: 'src/containers/Post',
|
||||
getData: (resolvedRoute) => {
|
||||
const path = resolvedRoute.route.path
|
||||
const author_id = path.split("/")[1]
|
||||
return client.query({
|
||||
query: GET_ARTICLE,
|
||||
variables: {author: author_id}
|
||||
}).then( (resp) => {
|
||||
const articles = resp.data.article;
|
||||
if(articles) {
|
||||
return {articles}
|
||||
}
|
||||
return {articles: []}
|
||||
})
|
||||
},
|
||||
})),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
7742
community/sample-apps/react-static-graphql/yarn.lock
Normal file
7742
community/sample-apps/react-static-graphql/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user