From ea8a14cc2856c7e8fc5a3a076ba2f6d15fdd7adf Mon Sep 17 00:00:00 2001 From: Trevor Blades Date: Fri, 9 Nov 2018 12:34:54 -0800 Subject: [PATCH 1/4] Add a practical example --- README.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e80626..f21d7f1 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,7 @@ A public GraphQL API for information about countries, continents, and languages. 1. The codes used to key the objects in the original data are available as a `code` property on each item returned from the API. 2. The `continent` and `languages` properties are now objects and arrays of objects, respectively. -Check out the [playground](https://countries.trevorblades.com) to explore the schema and test out some queries. - -## Example +## Writing queries ```graphql { @@ -46,3 +44,73 @@ Check out the [playground](https://countries.trevorblades.com) to explore the sc } } ``` + +Check out the [playground](https://countries.trevorblades.com) to explore the schema and test out some queries. + +## Example + +A practical use of this API is to create a country select input that doesn't require you to include a large dataset of country info in your bundle. + +In this example, we'll be using [React](https://reactjs.org/) and the [Apollo](https://apollographql.com) GraphQL client. First, we'll install all of our dependencies: + +```shell +$ npm install react react-dom react-apollo apollo-boost graphql graphql-tag +``` + +50.1 KB with `countries-list` +14.2 KB with Countries GraphQL + +```js +import React from 'react'; +import ReactDOM from 'react-dom'; +import ApolloClient from 'apollo-boost'; + +const client = new ApolloClient({ + uri: 'https://countries.trevorblades.com' +}); + +const GET_COUNTRIES = gql` + { + countries { + name + code + } + } +`; + +class App extends Component { + state = { + country: '' + }; + + onCountryChange = event => + this.setState({country: event.target.value}); + + render() { + return ( + + + {({loading, error, data}) => { + if (loading) return

Loading...

; + if (error) return

{error.message}

; + return ( + + ); + }} +
+
+ ); + } +} + +ReactDOM.render(, document.getElementById('root')); +``` From 0fd748b7921a10ae5e6ba19005c8d337fa4fbdcb Mon Sep 17 00:00:00 2001 From: Trevor Blades Date: Fri, 9 Nov 2018 16:55:20 -0800 Subject: [PATCH 2/4] Add example code --- README.md | 85 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index f21d7f1..f64fb2e 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,14 @@ [![Donate](https://img.shields.io/beerpay/trevorblades/countries.svg)](https://beerpay.io/trevorblades/countries) -A public GraphQL API for information about countries, continents, and languages. This project uses [Countries List](https://annexare.github.io/Countries/) as a data source, so the schema follows the shape of that data, with a couple exceptions: +A public GraphQL API for information about countries, continents, and languages. This project uses [Countries List](https://annexare.github.io/Countries/) as a data source, so the schema follows the shape of that data, with a few exceptions: 1. The codes used to key the objects in the original data are available as a `code` property on each item returned from the API. 2. The `continent` and `languages` properties are now objects and arrays of objects, respectively. -## Writing queries +## Querying + +In: ```graphql { @@ -26,6 +28,8 @@ A public GraphQL API for information about countries, continents, and languages. } ``` +Out: + ```json { "data": { @@ -45,30 +49,38 @@ A public GraphQL API for information about countries, continents, and languages. } ``` -Check out the [playground](https://countries.trevorblades.com) to explore the schema and test out some queries. +Check out [the playground](https://countries.trevorblades.com) to explore the schema and test out some queries. ## Example -A practical use of this API is to create a country select input that doesn't require you to include a large dataset of country info in your bundle. +One practical use of this API is to create a country select field that fetches its options dynamically. Normally, you would need to install an npm package or create a file in your project containing the necessary data -- usually country codes and names -- and bundle that data with your app code. This results in a lot of extra kilobytes hanging around in your bundle for a feature that might not always get rendered or used. Here's what that data size looks like: -In this example, we'll be using [React](https://reactjs.org/) and the [Apollo](https://apollographql.com) GraphQL client. First, we'll install all of our dependencies: +- **50.1 KB** using the `countries` export from [Countries List](https://annexare.github.io/Countries/) +- **14.2 KB** using this API (~70% smaller) + +In this example, I'll be using [React](https://reactjs.org/) and some [Apollo](https://apollographql.com) tools. Apollo's GraphQL client and React components make it simple to execute, handle, and cache GraphQL queries. You can also accomplish this by sending a POST request to this API using `fetch` or your favourite request library, but I won't cover that in this example. + +### Install dependencies ```shell $ npm install react react-dom react-apollo apollo-boost graphql graphql-tag ``` -50.1 KB with `countries-list` -14.2 KB with Countries GraphQL +### Build a React component ```js -import React from 'react'; -import ReactDOM from 'react-dom'; import ApolloClient from 'apollo-boost'; +import React, {Component} from 'react'; +import ReactDOM from 'react-dom'; +import gql from 'graphql-tag'; +import {Query} from 'react-apollo'; +// initialize our Apollo GraphQL client const client = new ApolloClient({ uri: 'https://countries.trevorblades.com' }); +// write a GraphQL query that asks for names and codes for all countries const GET_COUNTRIES = gql` { countries { @@ -79,38 +91,45 @@ const GET_COUNTRIES = gql` `; class App extends Component { - state = { - country: '' - }; + constructor(props) { + super(props); - onCountryChange = event => + // set a default value + this.state = { + country: 'US' + }; + } + + // set the selected country to the new input value + onCountryChange(event) { this.setState({country: event.target.value}); + } render() { return ( - - - {({loading, error, data}) => { - if (loading) return

Loading...

; - if (error) return

{error.message}

; - return ( - - ); - }} -
-
+ + {({loading, error, data}) => { + if (loading) return

Loading...

; + if (error) return

{error.message}

; + return ( + + ); + }} +
); } } ReactDOM.render(, document.getElementById('root')); ``` + +### Behold, your mighty country select 🎉 From 3c226f14012995bb9ca9188211256626f7728221 Mon Sep 17 00:00:00 2001 From: Trevor Blades Date: Fri, 9 Nov 2018 16:59:16 -0800 Subject: [PATCH 3/4] Add example --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f64fb2e..91e6f4b 100644 --- a/README.md +++ b/README.md @@ -60,13 +60,13 @@ One practical use of this API is to create a country select field that fetches i In this example, I'll be using [React](https://reactjs.org/) and some [Apollo](https://apollographql.com) tools. Apollo's GraphQL client and React components make it simple to execute, handle, and cache GraphQL queries. You can also accomplish this by sending a POST request to this API using `fetch` or your favourite request library, but I won't cover that in this example. -### Install dependencies +### 1. Install dependencies ```shell $ npm install react react-dom react-apollo apollo-boost graphql graphql-tag ``` -### Build a React component +### 2. Build a React component ```js import ApolloClient from 'apollo-boost'; @@ -132,4 +132,6 @@ class App extends Component { ReactDOM.render(, document.getElementById('root')); ``` -### Behold, your mighty country select 🎉 +### 3. Behold, your mighty country select 🎉 + +![faa4bd37fe24eed92b9e4453910b95b3](https://user-images.githubusercontent.com/1216917/48295448-add11200-e440-11e8-8215-95ed3b031cf9.gif) From 53cd32d8ab632eff35b7718f3141b7edae8503db Mon Sep 17 00:00:00 2001 From: Trevor Blades Date: Fri, 9 Nov 2018 17:26:46 -0800 Subject: [PATCH 4/4] Add a couple paragraphs at the end --- README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 91e6f4b..523378b 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,8 @@ Check out [the playground](https://countries.trevorblades.com) to explore the sc One practical use of this API is to create a country select field that fetches its options dynamically. Normally, you would need to install an npm package or create a file in your project containing the necessary data -- usually country codes and names -- and bundle that data with your app code. This results in a lot of extra kilobytes hanging around in your bundle for a feature that might not always get rendered or used. Here's what that data size looks like: -- **50.1 KB** using the `countries` export from [Countries List](https://annexare.github.io/Countries/) -- **14.2 KB** using this API (~70% smaller) +- **50.1 KB** with the `countries` export from [Countries List](https://annexare.github.io/Countries/) +- **14.2 KB** with this API (~70% smaller) In this example, I'll be using [React](https://reactjs.org/) and some [Apollo](https://apollographql.com) tools. Apollo's GraphQL client and React components make it simple to execute, handle, and cache GraphQL queries. You can also accomplish this by sending a POST request to this API using `fetch` or your favourite request library, but I won't cover that in this example. @@ -75,7 +75,7 @@ import ReactDOM from 'react-dom'; import gql from 'graphql-tag'; import {Query} from 'react-apollo'; -// initialize our Apollo GraphQL client +// initialize a GraphQL client const client = new ApolloClient({ uri: 'https://countries.trevorblades.com' }); @@ -90,7 +90,8 @@ const GET_COUNTRIES = gql` } `; -class App extends Component { +// create a component that renders an API data-powered select input +class CountrySelect extends Component { constructor(props) { super(props); @@ -129,9 +130,15 @@ class App extends Component { } } -ReactDOM.render(, document.getElementById('root')); +ReactDOM.render(, document.getElementById('root')); ``` -### 3. Behold, your mighty country select 🎉 +### 3. ??? + +### 4. Profit 🎉 ![faa4bd37fe24eed92b9e4453910b95b3](https://user-images.githubusercontent.com/1216917/48295448-add11200-e440-11e8-8215-95ed3b031cf9.gif) + +Now you've got a slick, self-contained country select component that only fetches its data when it's mounted. That means that if it exists within an unmounted route or the falsey end of a condition, it doesn't request any data or take up any extra space in your bundle. + +This is just one of many interesting things that you can build with this API. If you create something cool using this, let me know and I'll give you a shoutout here.