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.
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.
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.
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
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.
Let’s take a look at what we have for the
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, (
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.
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,
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
skill_level among other attributes.
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 (
.then we want to take THAT return value and we want to use it to
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!
In order to create a
Lesson you need to stipulate a couple of things. First,
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
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
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
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.
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.
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.