How to Use GraphQL with Ruby on Rails – Part 2 - React + Apollo Frontend
Tags: graphql, react, rails, tailwindcss
Published: 2019-12-05 17:30:27

---
title: How to Use GraphQL with Ruby on Rails – Part 2 - React + Apollo Frontend
published: true
date: 2019-11-28 21:38:31 UTC
tags: graphql, react, rails, tailwind
canonical_url: https://web-crunch.com/how-to-use-graphql-with-ruby-on-rails-part-2/
---

Continuing on from [Part 1](https://dev.to/justalever/how-to-use-graphql-with-ruby-on-rails-259a) is the frontend portion of the tutorial. I’ll leverage React, Apollo and Tailwind CSS to build out the frontend of our Ruby on Rails and GraphQL API application.


{% youtube TOq86ozyHIA %}

The tools I’m reaching for include the following:

- [React](https://reactjs.org/)
- [React Apollo](https://github.com/apollographql/react-apollo)
- [Tailwind CSS](https://tailwindcss.com/)
[Download the source code](https://github.com/justalever/graphql_fun_frontend_demo)
## Carrying over from Part 1

_Important note: I made an entire copy of the original app and created a new Github repo for you to download/reference. So if you’re coming from Part 1 you either need to carry on from it or clone the new repo._

Here are the steps I took to get the Rails API app up and running.

1. Clone the part 1 repo

```bash
$ git clone git@github.com:justalever/graphql_fun.git graphql_fun_frontend


$ cd/graphql_fun_frontend
$ bundle install
$ rails db:migrate
$ rails db:seed
$ rails server

```

The commands above _should_ get you a booted Ruby on Rails API application with some seeded data to query with GraphQL.

## Part 2 Setup

You could potentially separate your front-end completely from this project and have two separate apps communicating in tandem. We’ll be doing this but I’ll house the frontend app within the same repo as the Ruby on Rails app. Version control becomes a touch easier in my opinion for this but it also mixes concerns. To each their own so approach that how you wish.

### Rails API

For our front-end app to communicate “securely ” with the Rails API app we need to add a new gem called `rack-cors`. It should be commented out in your `Gemfile` at this point. Uncomment it and run `bundle install`

```ruby
# Gemfile
gem 'rack-cors'

```

Then, inside your `config/initializers/cors.rb` file you can uncomment the code there to match the following:

```ruby
# Be sure to restart your server when you modify this file.

# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.

# Read more: https://github.com/cyu/rack-cors

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'

    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

```

**Important:** When pushing this to a production environment you will want to change the `origins` to whatever remote domains your app lives on i.e. (`origins 'web-crunch.com', 'staging.web-crunch.com'`) and so on.

## React Frontend

Now on to the frontend portion. If you’ve been around the frontend scene for any amount of time recently you’ve probably heard of React. I won’t go into heavy detail of what React is or why you should/shouldn’t use it but rather direct you [to the docs](https://reactjs.org/) to see the benefits.

I personally am more of a Vue.js fan but React certainly has a large fan base.

All that aside, we’ll make use of `create-react-app` to get things set up pretty darn fast.

```bash
$ yarn global add create-react-app

```

I added the `create-react-app` module bundle globally so we could reference for other projects later. Consider this optional for your own system.

```bash
$ create-react-app frontend
$ cd frontend
$ yarn start

```

You may get a noticed about port 3000 being already in use. It will prompt you to use an alternate. I went ahead and said yes to the command. My frontend app now runs on `localhost:3001` in another browser tab.

To get a visual of the current directory structure I like to make use of `tree`.

On a mac you can run `brew install tree` to use it. Passing an `-I` plus a string of folders/files will ignore those.

```bash
$ tree . -I 'node_modules'
.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── serviceWorker.js
└── yarn.lock

2 directories, 16 files

```

A few notes:

- I’m not going to be worrying about front-end tests here for brevity sake
- We can delete the logo images and svgs since we’ll use our own assets

### Add Tailwind CSS

We need some dependencies installed to get Tailwind CSS dev-ready.

```bash
$ yarn add tailwindcss

$ yarn add postcss-cli autoprefixer -D // Save for dev use only

```

Initialize a config file:

```bash
$ yarn tailwind init --full

```

This generates a default `tailwind.config.js` file with the default scheme thanks to the `--full` flag.

Inside `index.css` lets scrap everything and add the tailwind directives.

```css
/* frontend/index.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

```

Add a `postcss.config.js` file within `frontend`

```javascript
// frontend/postcss.config.js

module.exports = {
  plugins: [
    require('tailwindcss')('tailwind.config.js'),
    require('autoprefixer'),
  ]
};

```

Let’s update our `package.json` scripts section to account for Tailwind

```
 "scripts": {
    "build:style": "tailwind build src/index.css -o src/tailwind.css",
    "start": "yarn build:style && react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

```

Your results may vary here depending on your own folder structure. The general idea is that we’ll add styles to `index.css` and output those to `tailwind.css` as compiled styles.

If your server is running at this point you should restart it:

```bash
$ yarn start

```

My updated `frontend` folder structure now looks like the following:

```bash
# graphql_fun_frontend/frontend 
$ tree . -I 'node_modules'
.
├── README.md
├── package.json
├── postcss.config.js
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── components
│   │   ├── App.js
│   │   └── Users.js
│   ├── index.css
│   ├── index.js
│   ├── serviceWorker.js
│   └── tailwind.css
├── tailwind.config.js
└── yarn.lock

3 directories, 15 files

```

Be sure to update your main `index.js` imports and `components/App.js` file. Notice I made a components folder for better organization as well. This is just a preference.

```javascript
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './tailwind.css';
import App from './components/App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));

serviceWorker.unregister();

```

And the `App.js` file

```javascript
// frontend/src/components/App.js
import React from 'react';

function App() {
  return (
    <div className="App">

    </div>
  );
}

export default App;

```

### Apollo

You may ask why Apollo? My answer is…mostly because it’s the easier/faster solution to querying GraphQL via the front-end. Are there other approaches out there? I’m 100% sure there are but the Apollo team are what I’d consider the pioneers of the approach. We’ll follow their conventions in this tutorial.

I’ll be leveraging:

- `react-apollo` – A React port for using Apollo within components.
- `apollo-boost` – Apollo Boost is a zero-config way to start using Apollo Client. It includes some sensible defaults, such as our recommended `InMemoryCache` and `HttpLink`, which come configured for you with our recommended settings. 
- `graphql` – GraphQL itself

```bash
$ yarn add react-apollo apollo-boost graphql

```

After those are installed we can extend `frontend/src/index.js` to include the following:

```javascript
// frontend/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './tailwind.css';
import App from './components/App';
import * as serviceWorker from './serviceWorker';
import { ApolloProvider } from 'react-apollo';
import { ApolloClient } from 'apollo-client';
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';

const link = createHttpLink({
  uri: 'https://localhost:3000/graphql' // This is relative to our Rails API port running on 3000
});

const client = new ApolloClient({
  link: link,
  cache: new InMemoryCache()
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);

serviceWorker.unregister();

```

With the `client` now passed down from `index.js`, we can start writing GraphQL queries. Let’s start with a `Users.js` component. Create a new file `src/components/Users.js`. Within that file import the following.

```javascript
// src/components/Users.js
import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
import Gravatar from 'react-gravatar';

```

We added one more dependency here for Gravatars.

```bash
$ yarn add react-gravatar # a handy gravatar package

```

Next, we can build a familiar query from Part 1. The file then becomes a bit longer.

```javascript
// src/components/Users.js
import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
import Gravatar from 'react-gravatar';

const GET_USERS = gql`
  {
    users {
      id
      name
      email
      postsCount
    }
  }
`;

```

Finally, we can build our `Users` component and pipe in the data. We’ll leverage Tailwind CSS for styling here. This also makes use of React hooks.

```javascript
import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
import Gravatar from 'react-gravatar';

const GET_USERS = gql`
  {
    users {
      id
      name
      email
      postsCount
    }
  }
`;

function Users() {
  const { loading, error, data } = useQuery(GET_USERS);

  if (loading) return 'Loading...';
  if (error) return `Error ${error.message}`;

  return (
    <div className="flex flex-wrap items-center">
      {data.users.map(user => (
        <div class="lg:w-1/3 w-full p-4 border" key={user.id}>
          <Gravatar email={user.email} size={150} className="w-full" />
          <h3 className="font-bold text-xl">{user.name}</h3>
          <p className="text-gray-500">{user.email}</p>
          <p className="text-gray-500">{user.postsCount} posts</p>
        </div>
      ))}
    </div>
  );
}

export default Users;

```

Within it, we destructure `{ loading, error, data }` variables for use. The main one being `data` which is what comes back thanks to our GraphQL query.

To actually render this component we need to import it inside `App.js`

```javascript
// frontend/src/components/App.js
import React from 'react';
import Users from './Users';

class App extends React.Component {
  render() {
    return (
      <div className="container mx-auto px-4">
        <Users />
      </div>
    );
  }
}

export default App;

```

That gets us some basic stuff in the view!

![https://i2.wp.com/i.imgur.com/57qeTMY.png?ssl=1](https://i2.wp.com/i.imgur.com/57qeTMY.png?ssl=1)

### User Profile & Posts View

Let’s create a singular profile page called `User.js` inside `src/components/User.js`. I’ll be using React Hooks where possible as we digress a bit further in creating more components. You can opt for the traditional React component approach as well. You’ll find I mix and match a bit.

For our User component, I went ahead and cleaned up a bit of code to extract some bits into smaller components. The `UserAvatar` component now can be used everywhere we want it as a result. It accepts a user prop.

First, we need to import those dependencies and components.

```javascript
// frontend/src/components/User.js
import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
import UserAvatar from './UserAvatar';
import Posts from './Posts';

```

Then add the `gql` query

```javascript
// frontend/src/components/User.js

const GET_USER = gql`
  query User($id: ID!) {
    user(id: $id) {
      posts {
        id
        title
      }
    }
  }
`;

```

And finally, the React Hook itself

```javascript
function User({ user, selectUser }) {
  const { loading, error, data } = useQuery(GET_USER, {
    variables: { id: user.id }
  });

  if (loading) return 'Loading...';
  if (error) return `Error ${error.message}`;

  return (
    <React.Fragment>
      <div className="flex flex-wrap my-4">
        <button
          className="bg-gray-200 hover:bg-gray-400 text-gray-900 font-bold py-2 px-4 rounded"
          onClick={selectUser.bind(this, null)}>
          Back
        </button>
      </div>
      <div className="flex flex-wrap items-start mb-4">
        <div className="lg:w-1/4 w-full rounded text-center">
          <UserAvatar user={user} />
        </div>
        <div className="px-4 flex-1 w-full">
          <Posts posts={data.user.posts} user={user} />
        </div>
      </div>
    </React.Fragment>
  );
}

export default User;

```

There is some code we reference here that hasn’t been addressed yet so let’s do that now.

```javascript
// frontend/src/components/UserAvatar.js

import React from 'react';
import Gravatar from 'react-gravatar';

const UserAvatar = ({ user }) => (
  <React.Fragment>
    <Gravatar email={user.email} size={200} className="rounded-full text-center inline" />
    <div className="px-6 py-4">
      <div className="font-bold text-xl mb-2">{user.name}</div>
      <p className="text-gray-500 text-sm">{user.email}</p>
      <p className="text-gray-500 text-base">{user.postsCount} posts</p>
    </div>
  </React.Fragment>
)
export default UserAvatar;

```

Above is the `UserAvatar` component. It wraps our `react-gravatar` import into a nice reusable package for us.

```javascript
// frontend/src/components/Posts.js
import React from 'react';

function Posts({ posts, user }) {
  return (
    <React.Fragment>
      <div className="lg:pl-10">
        <h1 className="font-bold mb-4">Posts from {user.name}</h1>
        {posts.map(post => (
        <div key={post.id}>
          <div className="p-6 shadow mb-4">
            <h3 className="text-2xl font-bold text-gray-800">{post.title}</h3>
          </div>
        </div>
      ))}
      </div>
    </React.Fragment>
  );
}

export default Posts;

```

Next is the `Posts` component which accounts for the rendering of each user’s posts.

### Update the main App.js Component

```javascript
// frontend/src/components/App.js
import React from 'react';
import User from './User';
import Users from './Users';

class App extends React.Component {
  state = {
    selectedUser: null
  }

  selectUser = (user) => {
    this.setState({ selectedUser: user })
  }

  render() {
    return (
      <div className="container mx-auto px-4">
        {this.state.selectedUser ?
        <User user={this.state.selectedUser} selectUser={this.selectUser} /> :
        <Users selectUser={this.selectUser} />}
      </div>
    );
  }
}

export default App;

```

Here we use a traditional React component and some state to manage if a user is indeed selected. If there’s an `onClick` fired we see a `User` profile instead of the `Users` listing.

### Create a User

Creating a user requires GraphQL Mutations. Our approach will be similar to our other components with a few variances.

Create a new component called `CreateUser.js`. Inside I added the following:

```javascript
import React, { Component } from 'react';
import gql from "graphql-tag";
import { Mutation } from "react-apollo";

const CREATE_USER = gql`
  mutation CreateUser($name: String!, $email: String!) {
    createUser(input: { name: $name, email: $email }) {
      user {
        id
        name
        email
        postsCount
      }
      errors
    }
  }
`;

class CreateUser extends Component {
  state = {
    name: '',
    email: ''
  }

  onSubmit = (e, createUser) => {
    e.preventDefault();
    createUser({ variables: this.state });
    this.setState({ name: '', email: '' });
  }

  render() {
    return (
      <Mutation
        mutation={CREATE_USER}
        update={this.props.onCreateUser}>
        {createUserMutation => (
          <div className="lg:fixed bottom-0 left-0 w-full bg-white border-t border-gray-300">
            <form className="lg:px-8 pt-2 pb-2" onSubmit={e => this.onSubmit(e, createUserMutation)}>
                <div className="lg:flex flex-wrap flex-between items-center justify-center lg:p-0 p-6">
                  <h4 className="font-bold lg:pr-4 mb-2">Create new user</h4>
                  <div className="lg:pr-4 mb-2">
                    <input
                      className="border rounded w-full py-2 px-3"
                      type="text"
                      value={this.state.name}
                      placeholder="Name"
                      onChange={e => this.setState({ name: e.target.value })} />
                  </div>
                  <div className="lg:pr-4 mb-2">
                    <input
                      className="border rounded w-full py-2 px-3"
                      type="email"
                      value={this.state.email}
                      placeholder="Email"
                      onChange={e => this.setState({ email: e.target.value })} />
                  </div>
                  <button
                    className="bg-blue-500 text-white py-2 px-4 rounded"
                    type="submit">
                    Create User
                  </button>

              </div>
            </form>
          </div>
        )}
      </Mutation>
    );
  }
}

export default CreateUser;

```

I chose to use traditional React render props instead of React hooks for this component. Being newer to react this version made more sense to me. We’re setting some state relative to the User object. To create a new user we need an email and name. Adding those happen on the frontend with a form. Using state we can capture events `onChange` to fire the `setState` method.

When the form is submitted we call a method `createUser` where we pass in the state. Once the state updates our GraphQL mutation is finally called.

In the end, the UI looks like the following:

![Screenshot_2019-11-19 How to use GraphQL with Ruby on Rails - Part 2 Frontend](https://i0.wp.com/i.imgur.com/31dsHRX.png?ssl=1)

The form is fixed to the bottom of the browser window but you can see I’ve added a couple of my own accounts with gravatar images.

### Wrapping Up

We’ve come a long way. GraphQL + React + Ruby on Rails can be a very powerful combo. I invite you to extend this app to account for creating posts as well. You’ll need to add new queries on both the backend and frontend to achieve this result.

If you followed along this far, I can’t thank you enough. Be sure to check out my other content as well as my [YouTube channel](htttps://youtube.com/c/webcrunch) to see more videos there.

If you’re brand new to Ruby on Rails I also created a full course on it called [Hello Rails](https://hellorails.io). It’s 90 videos of jam-packed knowledge about the awesome framework I use every day.

The post [How to Use GraphQL with Ruby on Rails – Part 2](https://web-crunch.com/how-to-use-graphql-with-ruby-on-rails-part-2/) appeared first on [Web-Crunch](https://web-crunch.com).