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!