Skip to content

Commit d9d8e2e

Browse files
Add simple React client that uses @defer
1 parent 3571df3 commit d9d8e2e

File tree

10 files changed

+7460
-13
lines changed

10 files changed

+7460
-13
lines changed

defer/client/.prettierrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"singleQuote": true
3+
}

defer/client/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Simple GraphQL React client using @defer
2+
3+
This React application demonstrates the usage of the @defer GraphQL statement.
4+
5+
This simple example will simulate the loading of a list of books. The books details, like title and author, are fast to fetch. However, the list of comments added for each book is much slower (in the real world, this list might be fetched from a separate micro-service with bad performance). Instead of waiting for the comments to load in order to show the list of books, or make two separate server calls, we use @defer in the `comments` field. The server will then respond with a Multipart Http response, first sending in the books details followed by the books comments.
6+
7+
## Running the example
8+
9+
You'll need a running GraphQL server on http://localhost:8080/graphql. You can use the example server from XXX (TODO: add link to the server implementation).
10+
11+
Then run:
12+
13+
```
14+
yarn start
15+
```
16+
to start the client React application.
17+
18+
That's it!
19+
20+
Navigate to http://localhost:3000 and you'll a list of books being rendered very quickly, followed by the list of comments for each book, which takes a few more seconds to load.

defer/client/package.json

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
{
2-
"name": "defer-client",
3-
"version": "1.0.0",
4-
"description": "",
5-
"main": "index.js",
2+
"name": "react-client",
3+
"version": "0.1.0",
4+
"private": true,
65
"dependencies": {
7-
"apollo-boost": "^0.1.16",
8-
"apollo-cache-inmemory": "^1.2.10",
9-
"apollo-client": "^2.4.2",
10-
"apollo-link-http": "^1.5.4",
6+
"apollo-boost": "^0.2.0-alpha.14",
117
"graphql": "^14.0.2",
12-
"graphql-tag": "^2.9.2"
8+
"react": "^16.5.1",
9+
"react-apollo": "^2.2.0-alpha.3",
10+
"react-dom": "^16.5.1",
11+
"react-scripts": "1.1.5"
1312
},
14-
"devDependencies": {},
1513
"scripts": {
16-
"test": "echo \"Error: no test specified\" && exit 1"
14+
"start": "react-scripts start",
15+
"build": "react-scripts build",
16+
"test": "react-scripts test --env=jsdom",
17+
"eject": "react-scripts eject",
18+
"lint:fix": "prettier --write src/**/*.js"
1719
},
18-
"author": "",
19-
"license": "MIT"
20+
"devDependencies": {
21+
"prettier": "^1.14.2"
22+
}
2023
}

defer/client/public/favicon.ico

3.78 KB
Binary file not shown.

defer/client/public/index.html

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6+
<meta name="theme-color" content="#000000">
7+
<!--
8+
manifest.json provides metadata used when your web app is added to the
9+
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
10+
-->
11+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
12+
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
13+
<!--
14+
Notice the use of %PUBLIC_URL% in the tags above.
15+
It will be replaced with the URL of the `public` folder during the build.
16+
Only files inside the `public` folder can be referenced from the HTML.
17+
18+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
19+
work correctly both with client-side routing and a non-root public URL.
20+
Learn how to configure a non-root public URL by running `npm run build`.
21+
-->
22+
<title>GraphQL @defer</title>
23+
</head>
24+
<body>
25+
<noscript>
26+
You need to enable JavaScript to run this app.
27+
</noscript>
28+
<div id="root"></div>
29+
<!--
30+
This HTML file is a template.
31+
If you open it directly in the browser, you will see an empty page.
32+
33+
You can add webfonts, meta tags, or analytics to this file.
34+
The build step will place the bundled scripts into the <body> tag.
35+
36+
To begin the development, run `npm start` or `yarn start`.
37+
To create a production bundle, use `npm run build` or `yarn build`.
38+
-->
39+
</body>
40+
</html>

defer/client/public/manifest.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"short_name": "React App",
3+
"name": "Create React App Sample",
4+
"icons": [
5+
{
6+
"src": "favicon.ico",
7+
"sizes": "64x64 32x32 24x24 16x16",
8+
"type": "image/x-icon"
9+
}
10+
],
11+
"start_url": "./index.html",
12+
"display": "standalone",
13+
"theme_color": "#000000",
14+
"background_color": "#ffffff"
15+
}

defer/client/src/app.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react';
2+
import ApolloClient from 'apollo-boost';
3+
import { ApolloProvider } from 'react-apollo';
4+
5+
import Books from './books';
6+
7+
const client = new ApolloClient({
8+
uri: 'http://localhost:8080/graphql'
9+
});
10+
11+
const App = () => (
12+
<ApolloProvider client={client}>
13+
<div>
14+
<h2>GraphQL @defer</h2>
15+
<Books />
16+
</div>
17+
</ApolloProvider>
18+
);
19+
20+
export default App;

defer/client/src/books.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import { Query } from 'react-apollo';
3+
import gql from 'graphql-tag';
4+
5+
const Comments = comments => (
6+
<ul>
7+
{comments &&
8+
comments.comments &&
9+
comments.comments.map(({ user, text }) => (
10+
<li key={text}>
11+
{user}: {text}
12+
</li>
13+
))}
14+
</ul>
15+
);
16+
17+
const Book = ({ title, author, comments }) => (
18+
<div>
19+
<p>{`${title} by ${author}`}</p>
20+
<Comments comments={comments} />
21+
</div>
22+
);
23+
24+
const Books = () => (
25+
<Query
26+
query={gql`
27+
{
28+
books {
29+
title
30+
author
31+
comments @defer {
32+
user
33+
text
34+
}
35+
}
36+
}
37+
`}
38+
>
39+
{({ loading, error, data }) => {
40+
if (loading) return <p>Loading...</p>;
41+
if (error) return <p>Error :(</p>;
42+
43+
return data.books.map(book => <Book key={book.title} {...book} />);
44+
}}
45+
</Query>
46+
);
47+
48+
export default Books;

defer/client/src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import App from './app';
4+
5+
ReactDOM.render(<App />, document.getElementById('root'));

0 commit comments

Comments
 (0)