React & Rails: Using Fetch to GET/PATCH

FETCH

So. You’ve started your new rails project. You’ve got some data stored in the database and now you want access to it. The problem is that you don’t want your Front-End to be in Rails, you wanna be all hip and cool – so you’re using React. Why is that a problem? Because React doesn’t flow seamlessly with Rails, so in order to get information from our database into our React components, we need to do a few things. Enter Fetch.

tenor

What is it? Fetch is an API that is used to asynchronously retrieve resources. You can fetch from anywhere, really. In our case, we will be fetching from our database. Let’s dive in.

Further Reading:

API Endpoints

If you do not have any experience with fetch then you likely do not know what API Endpoints are. They are exactly like they sound, an endpoint of communication that represents a collection of data. In our case, we are going to be creating an API controller that represents a list of lessons. This API controller will be what we fetch from in React and since fetch() utilizes promises we can retrieve that information in a much more succinct way and avoid callback hell.

Note: All of the examples in the post will be from my Breakable Toy project, Let’s Jam. To see all of the code for this project, please checkout my github repo – Let’s Jam.

First things first, let’s set up our API endpoint. Now, my database is already set up but this will work for anything you like. In my case, I have a table for lessons and if I go to my terminal and type in rails c to bring me to the console, then type in Lesson.all, I will get back all lessons in the database – simple.

In order to get all of those lessons over to React we need to set up an API endpoint, so let’s do it.

api endpoints directory

To start, you’re going to need to create a couple of folders and files. First, create folders for api and nested inside of that, v1. Inside of v1 we will host all of our API endpoint controllers. As you can see, I have 4 API endpoint controllers.

From here, we need to create the actual API controller, it is important to follow Rail conventions on naming here, so if you have a table, lessons, name your controller lessons_controller.rb.

You may be thinking to yourself at this point, isn’t this just like our normal controller? Kind of, yeah. As we progress you will see that it’s very similar in how we retrieve and update information to our database.

API Controller

Let’s take a look at what we have for the lessons_controller.rb file.

lessons API controller

Fairly similar to what you have already been working with in other controllers. In our specific case, we want to retrieve a list of all lessons from the database, but only if they are vacant (student_id is nil).

We use the index action because we are seeking to make an index page of all lessons, so it is important to match up controller actions as rails conventions will be doing the heavy lifting for us. If we put all of this in the show action, we would get nothing in response because Rails by default will be going to the index action. It knows to go to the index action in our controller based on the url that is defined in our fetch call, (/api/v1/lessons).

As for the logic in this action, it is very straightforward. We start by defining a new array to host all of our vacant lessons. We iterate through all of our lessons in the database and check to see if student_id is nil. If it is, we shovel it into our new array and then return it. I chose to shuffle it to make the page look a little more dynamic but this is just for flavor.

Now, in order to return the information, we need to use the line, render json:. This will return, as a response, a json (hash) of our data back to the requester (React fetch call). Now, let’s head over to the React side of things to take a look at how this request is working.

React Fetch()

lessons fetch calll in react

Here is a high-level breakdown of what is happening here. Anytime you go to the page that is rendering this component, upon mounting, a fetch call will be made to the database, through the API endpoint we previously setup. From there, a response will be generated in the form of a JSON. That response will be then set as state in the current component to the variable, lessons: [].

From here, if we were to throw in a debugger down in the render() function, we could run this.state.lessons and get back all of our information for lessons form the teacher_id, instrument, and skill_level among other attributes.

Now for fetch(). It is not as complicated as it looks. Just know this, as it will make EVERYTHING super easy to understand, every stage of the fetch returns something – no matter what. Ok. Let’s take a look.

/api/v1/lessons will return a bunch of data, this is because of our render function back on the API controller. Now, notice the next line says, .then(lessonResponse => lessonResponse.json()).

.then is a function as part of the promises syntax that says, take whatever was just explicitly returned and now do something to it. That something is defined in lessonResponse => lessonResponse.json(). lessonResponse could be named, rubberDuck => rubberDuck.json(), it doesn’t matter, it is a placeholder variable that simply represents whatever was returned.

So, we are saying, take whatever was returned form the fetch call and make sure it is in a readable form (json) and .then we want to take THAT return value and we want to use it to setState for lessons: [].

Now, we have successfully take information from our database and sifted it through Rails and into React. Now that this data is set to state in our React component, we are able to utilize it elsewhere in our React application!

Using fetch() to PATCH

We now know how to retrieve data from our backend, but what about storing new data from React? We basically do the same thing. It takes a couple of extra steps, but it isn’t too difficult. Let’s take a look!

patch reaxt to raisl.png

In order to create a Lesson you need to stipulate a couple of things. First, teacher_id, instrument and skill_level – these are all required through model validations. An optional field exists, though, for student_id. So, if a student wants to join a lesson, I need to find a way to add that user to the existing Lesson.

We start by taking as arguments, anything that will be required to make a PATCH request. In my case, that means the lesson_id (so we know what lesson the student is joining) and student_id (so we know what student to add). Now that these are argument of our method, let’s take a look at the actual fetch() request.

The first thing you will probably notice is that I am using string interpolation. Why? Because we want to target a specific Lesson and by extension, we want our fetch() request to be hitting the update action in the Lesson API controller. When we stipulate a specific lesson in the lessons_controller.rb file, Rails automatically knows it should avoid a series of action methods, like index.

It is the next line that will actually specify which action method to use. Look at the line, method: 'PATCH'. This is telling the controller that this request is seeking to take new information and append it to an existing entry in the database. Once Rails sees this, it automatically knows to use the update method. Let’s go back to the controller.

lessons API controller

Take a look at the update method. The update method require new information, but it also requires a way of identifying which database entry to update. To point to the entry we want to update, we use params[:id], this points Rails to the specific lesson we want to update. Since we have easy access to current_user which is the user who is currently signed in, we can just assign them to student . This is all a bunch of Rails magic! If you start getting some weird errors, throw in the credentials line, this has to do with Authenticating a user in Devise, before I included it I was unable to actually PATCH to the database.

Wrap Up

There you have it! You now know how both retrieve information from the database and alter it with PATCH requests. It’s unfortunate that Rails and React don’t get along as nice as we would like but at least we know some workarounds to achieve the results we’re looking for.

Again, naming conventions are still in play as we are working within a Rails framework. If you are getting funky errors about controllers or methods, check your file and class names to see if they are named properly.

Resources:

Submit a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s