Live Coding

Seamless GraphQL in Rails and React Native

Seamless GraphQL in Rails and React Native

by Jamon Holmgren and Morgan Laco

The video titled "Seamless GraphQL in Rails and React Native," presented by Jamon Holmgren and Morgan Laco at the Ancient City Ruby 2019 conference, aims to demonstrate how to effectively implement GraphQL within a Rails backend and a React Native frontend. The presenters outline their day jobs at Infinite Red, a consultancy focused on mobile and web design, where they leverage expertise in React and mobile development.

Key Points Discussed:

  • Introduction to the Speakers: Jamon Holmes shares his background as a co-founder of Infinite Red and a member of the React Native open source community, while Morgan Laco recounts his journey from Rails to mobile development with React Native.
  • Infinite Red Overview: Emphasizes the consultancy's focus on React and their recent projects involving AI and machine learning.
  • Tools Overview: Introduction of various tools including Rails, GraphQL Ruby for setting up GraphQL in Rails, and MST GQL for managing application state in React Native using MobX.
  • Demo Project: The talk features a live coding demo where they build a simple application that consumes a GraphQL API. They create a Rails backend with a Post model and corresponding GraphQL types and queries to illustrate how data can be fetched and manipulated.
    • The presenters install the GraphQL gem in Rails, create a scaffold for the Post model, and set up the GraphQL object with required fields. They utilize GraphiQL to showcase the flexibility of GraphQL in fetching specific data fields, addressing the limitations of traditional REST APIs.
  • Frontend Implementation: Transitioning to the React Native app, they incorporate MST GQL for managing data queries efficiently. They modify the Ignite Bowser app to include newly created GraphQL capabilities.
    • They also focus on the importance of synchronization between the backend and frontend schema to maintain a single source of truth, using rake tasks to manage GraphQL schema configurations.
  • User Interactions: The demo includes creating and deleting posts in the frontend while reflecting those changes accurately in the user interface. They highlight the benefits of GraphQL in improving collaboration with backend teams and enhancing overall developer experience.

Conclusions and Takeaways:
- This talk emphasizes the seamless integration of GraphQL with Rails and React Native, showcasing the advantages of using GraphQL over traditional REST APIs through live coding examples. The presenters encourage viewers to explore the tools demonstrated, and they provide access to a README for further guidance on the project. They conclude by thanking the audience and inviting questions, reiterating the potential of utilizing a unified schema across applications for improved development workflows.

00:00:12.610 Thank you very much! I'm Jamon Holmgren, and with me is Morgan Laco.
00:00:19.220 Morgan is going to be doing live coding while I narrate. This is a little bit of an analogy for our day jobs.
00:00:25.640 Morgan is a mobile software engineer at Infinite Red, and I am the CTO, which means I talk a lot.
00:00:33.140 So, Morgan, if you don't mind pulling up the slides that we created, I will go through those really quickly.
00:00:41.180 Fun fact: We practiced for a 30-minute talk and could never get it below 45 minutes. Then I realized it is actually a 45-minute talk, so that's perfect!
00:00:48.170 Okay, so our talk is about seamless GraphQL in Rails and React Native. Like I said, I'm Jamon Holmgren, and I live in the Pacific Northwest. It's really nice to be here right now and not there, where it's cold and wet.
00:01:00.409 I co-founded Infinite Red and work on the React Native open source community core. You can find me on Twitter at @JamonHolmgren.
00:01:07.070 Morgan?
00:01:12.110 I am Morgan Laco. I work at Infinite Red. I actually started with Rails at Code School, then went to Infinite Red and worked with Elixir at the beginning.
00:01:17.540 Then they switched me into mobile development with React Native. By the way, Morgan lives in Orlando.
00:01:23.180 A little bit about Infinite Red: we are a consultancy focused on mobile and web design. React is what we are most known for.
00:01:29.079 We are also starting to do some AI and machine learning projects as of January this year.
00:01:35.210 Alright Morgan, do you have the latest? I'm seeing a little problem here.
00:01:41.180 Thank you. Chain React is our conference focused on React Native. If you're attending React Native, please come and visit Portland in the summer, specifically in July.
00:01:48.170 I hear it gets a little warm here, so that's a good time to get out of the heat. The next one will be in July 2020.
00:01:56.080 You can find more about that at infinite.red/chainreactcomp.
00:02:01.540 Cool, so we're going to be talking about a lot of different tools during our live coding exercise.
00:02:07.990 We're not going to touch any of them too deeply, but there is a lot more depth.
00:02:14.200 Let's go through these tools very quickly. First up is Rails. Who here has heard of Rails?
00:02:19.650 Okay, a few of you! I won't talk about that too much because I know there are a lot of Rails developers here.
00:02:28.180 Now, GraphQL Ruby: has anybody used GraphQL Ruby?
00:02:33.790 Okay, actually a fair number. GraphQL Ruby is a gem that will provide our Rails generators and the GraphQL endpoint we're going to use.
00:02:40.690 We are going to generate a GraphQL schema. That's one of the main points of this talk.
00:02:45.760 We want to show how you can have one schema between your backend and your mobile app.
00:02:51.280 You can also translate this to the web as well. I'm doing a mobile app to illustrate this.
00:02:56.709 We'll also show how to implement this on a web frontend.
00:03:04.030 We will be using a tool called MST GQL to generate our MobX state tree models from the GraphQL schema.
00:03:10.209 Think of MobX state tree as being Redux-like state management but with some better features.
00:03:16.170 We've used Redux for several years at Infinite Red, but we got tired of the boilerplate.
00:03:21.519 MobX state tree is probably the most popular alternative to Redux you will find.
00:03:27.370 We'll also be using React Native with our starter kit called Ignite Bowser.
00:03:32.710 This is a boilerplate for React Native that will save you about two weeks of initial setup.
00:03:39.400 We'll be starting off with a fresh Ignite Bowser setup. We haven't modified it much, just ensured all of our dependencies are installed.
00:03:45.460 Go ahead and proceed to the next step.
00:03:52.150 This is what we'll be building. Morgan, could you confirm?
00:03:57.640 Yes, we're building a simple demo to demonstrate how to consume an API using GraphQL on a React Native client.
00:04:01.990 We're keeping it simple here because we only have 45 minutes.
00:04:08.210 We'll be doing live coding. Head to the next screen quickly.
00:04:18.289 Since we're introducing multiple tools, I want you to take your mobile phone or laptop and go to get.io/JAECR or scan the QR code.
00:04:29.990 This will redirect you to a README we're following today. Morgan and I wrote it, and you can follow along too.
00:04:36.520 Everything is open source, and we will do our best to explain the code as we go.
00:04:43.130 But just in case you want to spend a little more time on something, feel free to.
00:04:49.570 So get.io/JAECR or scan the QR code to access the GitHub repo.
00:04:56.370 Alright, let's do the demo.
00:05:01.130 On our left, we have our Rails app—a brand new Rails 6.0 project. It's completely fresh.
00:05:09.270 On the right, there's a fresh Ignite Bowser React Native app. The first thing we’ll do is add the GraphQL Ruby gem.
00:05:16.990 Let's open up VS Code here to ensure we have the GraphQL gem installed.
00:05:23.680 We actually already have it installed to avoid using hotel Wi-Fi.
00:05:28.740 Now, let’s open up the terminal and run the generator that comes with the GraphQL Ruby gem.
00:05:35.130 Rails G GraphQL: install will bring in all the necessary files for working with the GraphQL endpoint and schema.
00:05:41.610 Next, we will create a scaffold. A lot of Rails developers don't really use scaffolds, but they are good for demo purposes.
00:05:50.190 So, let's run Rails G scaffold to create a Post model with attributes of title and body, both as strings.
00:05:56.100 Then, we can run Rails DB:migrate to apply our new model.
00:06:04.650 This creates the Post model along with basic views for creating, editing, and deleting posts.
00:06:10.740 Next, we are going to create the corresponding GraphQL object. This will help us leverage GraphQL for our Rails app.
00:06:19.920 Let's run Rails G GraphQL:Object Post and define its fields.
00:06:27.900 The fields will include an ID, title, and body. All fields need to match the attributes we defined earlier.
00:06:35.120 Alright, let’s quickly check that we have the PostType.rb file.
00:06:40.000 You will see it under the GraphQL folder that was created, featuring the three fields we defined.
00:06:48.570 Next, we’ll move to our QueryType.rb file. Here is where we define the types of queries that can be run against our GraphQL endpoint.
00:06:56.000 We will also hook it up to the Post object we created earlier.
00:07:02.040 Morgan, let's copy and paste that in. I’ll walk you through what’s happening.
00:07:08.100 To save time, we’re copying and pasting, but I’ll explain everything to avoid any errors.
00:07:15.530 The posts field defines what we’re returning back - an array of posts of the Post type.
00:07:23.589 We implement it using a method that performs a regular active record request to return all the posts.
00:07:30.309 We could sort or filter them based on arguments, but we'll keep it basic and stick to fetching all the posts.
00:07:40.399 To see this in action, let’s run Rails server and navigate to localhost:3000/posts.
00:07:50.469 Given that the server is running, we should be able to create a new post.
00:07:58.489 We can add some content to it; Morgan, go ahead and create another post.
00:08:06.469 Great! Now that we have some content, let's jump to GraphiQL.
00:08:15.090 GraphiQL is a UI that comes with the GraphQL Ruby gem, allowing you to run queries and see responses.
00:08:21.790 It's incredibly helpful during development. One cool thing is that GraphQL allows you to shape data as you need it.
00:08:29.589 Let's run an example query. The field name we defined earlier was 'posts', so type that in.
00:08:36.449 When we run it, we’ll see a data property that has posts, which is an array.
00:08:43.930 Currently, we’re only getting IDs back, which isn't very useful, so let's add some fields.
00:08:49.990 GraphiQL features autocomplete, making this a very efficient tool for developers.
00:08:56.129 After adding more fields, run the query again, and this time we will see expanded data returned.
00:09:03.890 This is one of the best aspects about GraphQL: you can request only the fields you need.
00:09:10.820 This leads to better experiences for front-end developers because they have control over what data they receive.
00:09:17.540 At Infinite Red, most of our work involves collaborating with backend teams.
00:09:24.750 With traditional REST APIs, we’re often limited by what backend teams can implement.
00:09:31.180 But with GraphQL, we can request exactly what we need, significantly improving our workflow.
00:09:38.227 Morgan particularly likes that GraphQL is composable. If we add authors, we can easily fetch their details without altering the API.
00:09:45.080 That’s right! If we had an authors field, we could simply query for it.
00:09:51.530 With correct setup, GraphQL efficiently manages related data without causing N+1 query issues.
00:09:58.170 Alright, now that our backend is pretty much done for this initial version, let's move to the frontend.
00:10:05.720 We need to implement the React Native Ignite Bowser app to query this schema.
00:10:12.650 Let's create a rake task for easier schema management in our Rails app.
00:10:19.780 We can use rails G task GraphQL dump to generate a task that outputs our current schema.
00:10:27.000 Let’s navigate to that file in the 'lib/tasks' directory.
00:10:35.280 The command we ran earlier generates a new object in our Rails schema.
00:10:42.490 This command will return the definition of our GraphQL schema, which we will write to a file.
00:10:50.709 Next, let's run the rake task we created by using rake GraphQL: dump.
00:10:58.020 This step is crucial because as our backend evolves, we need to synchronize changes with the frontend.
00:11:04.380 We want to keep a single source of truth for our schema to avoid inconsistencies.
00:11:11.330 Let’s open the GraphQL file we just generated, located at the root of our project.
00:11:17.600 Here, we see the types we defined, including post with its fields ID, body, and title.
00:11:25.530 Next, we need to update the GraphQL controller that was generated during the install process.
00:11:33.129 This controller sets up the endpoint we will be using for the mobile app.
00:11:39.620 Because we’re working with a mobile app, we need to adjust our cross-site scripting settings.
00:11:47.500 We need to add a line at the top to protect from forgery with nil session.
00:11:54.010 This essentially disables the default protection, but remember to implement your own safety measures.
00:12:01.860 Alright, we've finalized the Rails app. Now we need to display the posts in our React Native app.
00:12:07.700 Let's open the React Native simulator; this is how an Ignite Bowser app looks out of the box.
00:12:15.320 If you've installed Ignite and created a new app, this is the initial setup you can expect.
00:12:22.480 React Native is cross-platform, running on both iOS and Android.
00:12:28.709 Let me explain more about Ignite: we began working with React Native in 2015.
00:12:34.320 Initially, we recognized a lack of best practices in setting up a React Native app.
00:12:40.610 After searching for boilerplates, we decided to create our own, which led to Ignite.
00:12:48.090 We've since refined Ignite and released a second version called Bowser.
00:12:54.270 We will regularly update Ignite with new features and best practices.
00:13:02.250 If you continue through Ignite, you can explore various demo features.
00:13:07.450 Rich Evans is here and is the primary maintainer of Reactotron, a desktop app to inspect React Native apps.
00:13:13.300 Reactotron can also be used with standard React apps, providing logging and debugging capabilities.
00:13:21.019 However, for now, we will focus on editing the welcome screen to display posts.
00:13:26.950 The first step is to add MSTGQL to our project.
00:13:33.630 We can run yarn add MST GQL GraphQL request to do this.
00:13:41.290 MSTGQL provides functionality to request data from the Rails server.
00:13:46.920 On the right side, we see our React Native app with the necessary dependencies.
00:13:53.200 MSTGQL also comes with a runtime component for making requests.
00:14:01.090 We will create a custom hook after Jake discussed hooks, which will help us manage queries.
00:14:07.750 Let's proceed and run the command yarn MST GQL to generate necessary files.
00:14:14.700 We're using Typescript with this demo, similar to Flow, to maintain type safety.
00:14:23.340 MST GQL will utilize the GraphQL schema to generate Typescript types.
00:14:30.130 We will indicate where the schema lives, which will produce corresponding files.
00:14:36.950 An important aspect to note is that the script can be executed multiple times.
00:14:43.790 It's crucial not to edit the generated files directly; instead, we will inherit from them.
00:14:50.540 Now, we need to import the generated model into our app.
00:14:56.150 We want to utilize the root store base that we’ll be implementing for the application.
00:15:02.220 We can keep route stores organized as children for ease of access across the app.
00:15:10.550 Revamping the root store model will help us manage properties seamlessly.
00:15:19.050 We can get back to the root store base and ensure we have correct typings in place.
00:15:28.470 The environment file will handle setup for our GraphQL requests.
00:15:38.290 To initialize our context, we'll use createStoreContext to achieve this.
00:15:45.570 Our custom hooks will assist in managing queries to fetch data effortlessly.
00:15:54.000 Now, let’s return to the welcome screen and inject the GraphQL capabilities.
00:16:05.450 The welcome screen contains JSX that will build the UI.
00:16:12.890 We’ll add the necessary hooks there to manage the queries for the posts.
00:16:20.360 The useStore hook will allow us to access the stores defined in the application.
00:16:27.610 This allows us to map through the posts and render their titles.
00:16:35.820 To show these changes, let’s incorporate a stylized button for deleting posts.
00:16:40.570 When the user clicks this button, it will trigger the delete action.
00:16:47.940 Now, let's ensure that we properly update the UI with this information.
00:16:60.800 The action will handle the state and re-render the component to reflect the deletion.
00:17:07.050 So let's implement the changes and refresh to see the results.
00:17:14.400 By running the app in the simulator, we will see how posts are displayed.
00:17:22.860 We should also add the touchable button that will execute the delete query.
00:17:29.610 The delete operation will require an ID to specify which post to remove.
00:17:37.080 During refresh, the user will see updated posts reflecting the deleted ones.
00:17:43.900 After hitting delete, verify signatures are not visible in the inventory.
00:17:51.470 Now that we have implemented the mutation, everything should work as planned.
00:17:58.370 Replacing text in components when refreshed will show the new state.
00:18:05.200 Our goal was to set up a seamless experience fetching data and managing states.
00:18:13.020 Despite facing some technical glitches, we managed to cover everything.
00:18:20.830 You can access the README markdown, which contains additional insights.
00:18:28.000 We’ll share the presentation with more resources and links to Infinite Red.
00:18:35.390 Thank you for participating, and I look forward to your questions!
00:18:41.870 Thank you!