In the last post I have played with GraphQL. The next step is to actually query the data and display it.

In this post I will use react (from Facebook) and the Apollo GraphQL client.

Tooling

React

I won’t give in here an introduction of the language because you may find on the web thousands of very good tutorials and advocacy articles. Anyway I will explain briefly why I have chosen React.

It ain’t no secret to anyone: I am not a UI guy. Actually I hate Javascript… Well I hated what was javascript until recently.

I have heard a lot about React. As I am curious, I decided to give it a try.

The JSX syntax (the core syntax of react) is very clear. On top of that, the adoption of Ecmascript 6 make it an elegant and robust language.

React is component based, object oriented and relatively easy to learn.

On top of that, I have always planed to develop a mobile app (at least for fun). The “React Native” project would be a perfect fit to do so. But I will keep that for another moment when I am more Skilled with react.

react-table

A lot of react libraries are available to render tables.

I did some research, and I found that the project react-table was the more documented and easy to use.

Apollo

When it comes to GraphQL integration we have the choice between two major projects:

  • Relay which is self described as A Javascript framework for building data-driven react applications
  • Apollo described as The flexible, production ready GraphQL client for React and native apps

Of course, as I knew nothing, I googled for some help about which framework I should use.

I found an excellent article on codazen: Choosing a GraphQL Client: Apollo vs. Relay. To be honest I didn’t understand half of the concepts that were compared, but one of those was enough to help me in my choice.

The documentation of the Apollo project is exposed as “fantastic (with pictures)!”. And as a newbie, I will need to refer to a strong documentation. That doesn’t mean that I will not change later nor that this framework is better. That only means that I will use it for my first experiment.

VIM

https://xkcd.com/378/

When I was at university I was an emacs guy… but when I started to work as a sys-admin I fell into vi/m. And by now I can hardly imagine using something else. So vim will be my choice to edit react.

To use it decently, I have installed two plugins via [vundle:

1# from my ~/.vimrc
2Plugin 'pangloss/vim-javascript'
3Plugin 'mxw/vim-jsx'     

I have also installed eslint which is a pluggable linting utility compatible with syntastic.

1sudo npm install -g eslint
2sudo npm install -g babel-eslint
3sudo npm install -g eslint-plugin-react              

I have also configured syntastic to understand correctly the javascript and the react syntax by using

1# from my ~/.vimrc
2let g:syntastic_javascript_checkers = ['eslint'] 

Let’s code

Installing react

The installation of react is pretty straightforward:

1sudo npm install -g react_
2sudo npm install -g create-react-app

The create-react-app is a helper program that pre-configure a lot of stuff for you (such as babel or webpack) to focus on the code instead of the tooling.

Creating the basic apps

1create-react-app blog-test

This will create a directory blog-test, download all the base packages that are necessary for a hello-world app and create an application skeleton.

At the end, the output should be something like:

Success! Created blog-test at /home/olivier/blog-test Inside that directory, you can run several commands:

So if do what’s suggested, you can open you browser and point to localhost:3000 and get sonething that looks like that:

Installing the dependencies

As explained, I will used the Apollo and react-table dependencies. Let’s install them first:

1npm install react-apollo --save
2npm install react-table

Let’s write the code of the application

The code of the application is located in the file src/App.js. It is a class that inherit from the React.Component.

Setting up Apollo and the graphql connection

We will use Apollo to setup the connection to the GraphQL server we coded last time in go. First, we need to import the Apollo dependencies:

1import { ApolloClient, ApolloProvider, createNetworkInterface } from 'react-apollo';

Then we will instanciate the connection in the Constructor of the App component as written in Apollo’s documentation:

 1class App extends Component {
 2   constructor(props) {
 3     super(props);
 4     const networkInterface = createNetworkInterface({
 5       uri: 'http://localhost:8080/graphql'
 6     })
 7 
 8     this.client = new ApolloClient({
 9       networkInterface: networkInterface
10     });
11   }
12 
13   render() {
14   ...

Note : The version of the server on github has been tweaked to handle the CORS Preflight request.

Then for now, we Setup the ApolloProvider component to do nothing in the render method:

1...
2render() {
3  return (
4    <div className="App">
5      <ApolloProvider client={this.client}>
6      </ApolloProvider>
7...

Defining the table

To use the react-table, we need to import the component:

1import ReactTable from 'react-table'
2import 'react-table/react-table.css'

Note : I also import the CSS

Then we create the columns headers as expected by the react-table component (it is well described in the documentation):

Here we want to display the product SKU, its location, the instance type and the operatingSystem.

 1const columns = [{
 2    header: 'SKU',
 3    accessor: 'sku' // String-based value accessors!
 4  }, {
 5    header: 'Location',
 6    accessor: 'location',
 7    sortable: true,
 8  }, {
 9    header: 'Instance Type',
10    accessor: 'instanceType'
11  }, {
12    header: 'Operating System',
13    accessor: 'operatingSystem'
14}]

Then we create a component ProductList that will render the table:

 1function ProductList({ loading, products }) {
 2   if (loading) {
 3     return <div>Loading</div>;
 4   } else {
 5     return (
 6       <div className="App">
 7       <ReactTable className="-striped -highlight"
 8         data={products}
 9         columns={columns}     
10       />
11       </div>
12     );
13  } 
14} 

Then we change the render function to use the ProductList instead of the default view:

 1...
 2render() {
 3  return (
 4    <div className="App">
 5      <ApolloProvider client={this.client}>
 6        <ProductList />
 7      </ApolloProvider>
 8    </div>
 9  );
10}

If you did everything correctly, you shoud see this:

Now let’s query:

To use the Graphql components of Apollo, we need to import them:

1import { gql, graphql } from 'react-apollo';

Then, let’s create the query as a constant in the exact same manner as when we did it with GraphiQL (cf last post):

 1const allProducts = gql`
 2query products {
 3  products{
 4    sku
 5    location
 6    instanceType
 7    operatingSystem
 8  }                                                                                                                                                                                                             
 9}
10`

Now the “tricky” part: We must change the Component ProductList to use our Data. This is documented on the Apollo Website under the section Requesting Data:

The graphql() container is the recommended approach for fetching data or making mutations. It is a React Higher Order Component, and interacts with the wrapped component via props.

As written in the doc, let’s create a component ProductListWithData:

1const ProductListWithData = graphql(allProducts, {
2  props: ({data: { loading, products }}) => ({
3    loading,
4    products,
5  }),
6})(ProductList);

And use it within the Apollo provider instead of the ProductList Component

 1...
 2render() {
 3  return (
 4    <div className="App">
 5      <ApolloProvider client={this.client}>
 6        <ProductListWithData />
 7      </ApolloProvider>
 8    </div>
 9  );
10}

Conclusion

Et VoilĂ … If you:

  • start the graphql-test server from the last post
  • start the dev environment with npm start inside the blog-test folder
  • go to http://localhost:3000

You should see something like:

Screenshot

This was a very quick introduction. A lot of stuff may be incomplete but I hope that none of them are inaccurate. Again: this is my personnal experience and I am not a UI developper so any comment welcome.