I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. And when it has gone past I will turn the inner eye to see its path. Where the fear has gone there will be nothing. Only I will remain.
- "Litany Against Fear," Frank Herbert, Dune
You may be wondering, "What does fear have to do with a React app?" First of all, there's nothing to fear in a React app. In fact, in this particular app, we banned fear. Isn't that nice?
Now that you're ready to be fearless, let's discuss our app. It's a mini Yelp clone where instead of reviewing restaurants, users review planets from the classic sci-fi series, Dune. (Why? Because there's a new Dune movie coming out... but back to the main point.)
To build our full-stack app, we'll use technologies that make our lives easy.
React: Intuitive, compositional front-end framework, because our brains like to compose things.
GraphQL: You may have heard many reasons why GraphQL is awesome. By far, the most important one is developer productivity and happiness.
Hasura: Set up an auto-generated GraphQL API on top of a Postgres database in under 30 seconds.
I see you're a skeptical one. But you'll most likely come around as soon as you spend some time with GraphiQL (the GraphQL playground).
Using GraphQL is a breeze for the front-end developer, compared to the old ways of clunky REST endpoints. GraphQL gives you a single endpoint that listens to all your troubles... I mean queries. It's such a great listener that you can tell it exactly what you want, and it will give it to you, nothing less and nothing more.
Feeling psyched about this therapeutic experience? Let's dive into the tutorial so you can try it ASAP!
The first step of every good journey is sitting down with some hot tea and sipping it calmly. Once we've done that, we can deploy to Heroku from the Hasura website. This will set us up with everything we need: a Postgres database, our Hasura GraphQL engine, and some snacks for the journey.
Step 2: Create planets table
Our users want to review planets. So we create a Postgres table via the Hasura console to store our planet data. Of note is the evil planet, Giedi Prime, which has been drawing attention with its unconventional cuisine.
Meanwhile in the GraphiQL tab: Hasura has auto-generated our GraphQL schema! Play around with the Explorer here ??
Step 3: Create React app
We'll need a UI for our app, so we create a React app and install some libraries for GraphQL requests, routing, and styles. (Make sure you have Node installed first.)
Step 4: Set up Apollo Client
Apollo Client will help us with our GraphQL network requests and caching, so we can avoid all that grunt work. We also make our first query and list our planets! Our app is starting to shape up.
We test our GraphQL query in the Hasura console before copy-pasting it into our code.
Step 5: Style list
Our planet list is nice and all, but it needs a little makeover with Emotion (see repo for full styles).
Step 6: Search form & state
Our users want to search for planets and order them by name. So we add a search form that queries our endpoint with a search string, and pass in the results to Planets to update our planet list. We also use React Hooks to manage our app state.
Step 7: Be proud
We've already implemented our planet list and search features! We lovingly gaze upon our handiwork, take a few selfies together, and move on to reviews.
Part 2: Live reviews
Step 1: Create reviews table
Our users will be visiting these planets, and writing reviews about their experience. We create a table via the Hasura console for our review data.
We add a foreign key from the planet_id column to the id column in the planets table, to indicate that planet_ids of reviews have to match id's of planets.
Step 2: Track relationships
Each planet has multiple reviews, while each review has one planet: a one-to-many relationship. We create and track this relationship via the Hasura console, so it can be exposed in our GraphQL schema.
Now we can query reviews for each planet in the Explorer!
Step 3: Set up routing
We want to be able to click on a planet and view its reviews on a separate page. We set up routing with React Router, and list reviews on the planet page.
Step 4: Set up subscriptions
We install new libraries and set up Apollo Client to support subscriptions. Then, we change our reviews query to a subscription so it can show live updates.
We've implemented planets with live reviews! Do a little dance to celebrate before getting down to serious business.
Part 3: Business logic
Step 1: Add input form
We want a way to submit reviews through our UI. We rename our search form to be a generic InputForm and add it above the review list.
Step 2: Test review mutation
We'll use a mutation to add new reviews. We test our mutation with GraphiQL in the Hasura console.
And convert it to accept variables so we can use it in our code.
Step 3: Create action
The Bene Gesserit have requested us to not allow (cough censor cough) the word "fear" in the reviews. We create an action for the business logic that will check for this word whenever a user submits a review.
Inside our freshly minted action, we go to the "Codegen" tab.
We select the nodejs-express option, and copy the handler boilerplate code below.
We click "Try on Glitch," which takes us to a barebones express app, where we can paste our handler code.
Back inside our action, we set our handler URL to the one from our Glitch app, with the correct route from our handler code.
We can now test our action in the console. It runs like a regular mutation, because we don't have any business logic checking for the word "fear" yet.
Step 4: Add business logic
In our handler, we add business logic that checks for "fear" inside the body of the review. If it's fearless, we run the mutation as usual. If not, we return an ominous error.
If we run the action with "fear" now, we get the error in the response:
Step 5: Order reviews
Our review order is currently topsy turvy. We add a created_at column to the reviews table so we can order by newest first.
reviews(order_by: { created_at: desc })
Step 6: Add review mutation
Finally, we update our action syntax with variables, and copy paste it into our code as a mutation. We update our code to run this mutation when a user submits a new review, so that our business logic can check it for compliance (ahem obedience ahem) before updating our database.
If we submit a new review that includes "fear" now, we get our ominous error, which we display in the input field.
Step 7: We did it! ?
Congrats on building a full-stack React & GraphQL app!
What does the future hold?
If only we had some spice melange, we would know. But we built so many features in so little time! We covered GraphQL queries, mutations, subscriptions, routing, searching, and even custom business logic with Hasura actions! I hope you had fun coding along.
What other features would you like to see in this app? Reach out to me on Twitter, and I'll make more tutorials! If you're inspired to add features yourself, please do share – I'd love to hear about them :)