diff --git a/README.md b/README.md index 3e80626..523378b 100644 --- a/README.md +++ b/README.md @@ -4,14 +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. -Check out the [playground](https://countries.trevorblades.com) to explore the schema and test out some queries. +## Querying -## Example +In: ```graphql { @@ -28,6 +28,8 @@ Check out the [playground](https://countries.trevorblades.com) to explore the sc } ``` +Out: + ```json { "data": { @@ -46,3 +48,97 @@ 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 + +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** 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. + +### 1. Install dependencies + +```shell +$ npm install react react-dom react-apollo apollo-boost graphql graphql-tag +``` + +### 2. Build a React component + +```js +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 a 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 { + name + code + } + } +`; + +// create a component that renders an API data-powered select input +class CountrySelect extends Component { + constructor(props) { + super(props); + + // 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 ( + + ); + }} +
+ ); + } +} + +ReactDOM.render(, document.getElementById('root')); +``` + +### 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.