Fetching Blog Comments from a Database with a Custom React Hook

In this lesson, we'll create a React hook that will fetch the comments from the database. We'll cover how to create a custom hook as well as how to integrate with Hasura.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the The newline Guide to Full Stack Comments with Hasura and React course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to The newline Guide to Full Stack Comments with Hasura and React, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course The newline Guide to Full Stack Comments with Hasura and React

In the previous lesson, we introduced a sample block application that will be our use case for a commenting system. We saw a pages/posts/slackts file which contains a post- component. This component is responsible for rendering post-content and details and that's where we're going to add comment section and a form to add a new comment. When a user visits a particular post, for example the first one, dynamic routing, we need to fetch the post's comments. That means we need to fetch those entries from the table's comments that have topics set to dynamic routing. So what are our requirements for fetching the comments? Let's open the slackts. txt file and list what should happen there. On the component load, we need to fetch comments added for a particular block post from our Hasura instance. We need a few state variables to store information. Comments, at first it's an empty list which will update after successfully fetching the comments. Loading, a boolean variable indicating whether fetching is in progress. Error, a variable indicating that there was an error will fetch in comments. By default, it will be null if an error occurs, will set it to a string with an error message. We could keep this logic in this file and that would be fine. However, we'll extract it into separate custom hook which will let us test the hook separately and reuse it in other components. A node from React docs on implementing custom hooks. Unlike a React component, a custom hook doesn't need a specific signature. We can decide what it takes as arguments and what if anything it should return. In other words, it's just like a normal function. Its name should always start with use so that you can tell at the glance that the rules of hooks apply to it. As hooks should have used prefix and our subject is comments, we 'll call our hook use comments. Let's create a new file in the lib directory and call it use comments .ts. Instead of going straight to writing implementation details, we first model the hook with TypeScript types. When we focus on types without being distracted by the implementation, we're more likely to consider multiple ideas and compare the alternatives. It allows us to stop for a moment and think about what we need, what is the ideal API and how we like to use it. Let's start from something that is kind of the base of our commenting system, a comment type. In the previous module, we created a table comments so the type should map the database model. Here's how it looks in TypeScript. I will declare a new interface with fields topic, outer, content and created add. All of the fields will be string. Notice that created add is typed as string. It's because we get an ICO string from GraphQL API. It's not being transformed into JavaScript state even though it's typed as timestamp in the schemas pack. Graph QL comes with default scalar types like int, load, string, boolean and id. But it also allows defining custom scalar types. timestamp is one of the examples and it's being sent as a string from the API. On the client, we can manually parse it to a date type. As we have the comments type, let's write down the hook function signature. Our hook will take two arguments. Hasura URL and URL to our Hasura backend. We could hide it inside the hook implementation but this way we can make the hook more generic. We can reuse it to connect to different Hasura instances. The second argument is topic and identifier of the content. For example, my blog post about cats. The hook returns an object and I will call it use comments result. And by the way, right now I'm using the clear keyword to tell the compiler about types before we write any implementation. Now let's create the use comments result type. What information do we need from the hook? Most importantly, comment and array of objects of type comment. Loading. As we mentioned earlier, it will indicate whether the comments are being fetched. Error, a variable with an error message. And here we go, we can proceed to the implementation details now. Firstly, let's declare all the state variables that we mentioned before. As previously, I will use use seed hook and declare comments error and loading. As the second step, let's create a fetch comments function. And here's what's going to happen inside of this function. Firstly, we will set the loading to true as we begin fetching the comments. Then we'll use a native fetch API to connect with Hasura and retrieve the comments. As we mentioned in the previous module, under the hood, the graphical request is just a post request over HTTP. We mentioned that there are multiple client libraries. However, our use case is simple enough that the built-in fetch is all we need. Let's break the second point into smaller pieces. The fetch function takes two arguments. The first one is an endpoint URL. In our case, it's the URL provided as the first argument of the hook. Then there is a request config. In the request config, we'll specify three things. The method, it's post, in our case, then the headers. We need to provide the X Hasura role header set to anonymous. We're also setting content type to application/json, which designates the content to be in JSON format. Then the third thing is the actual graphical request body. Here we should pass a stringified object with query and variable skis. Let's go back for a moment to the Hasura console and construct a query with graphical explorer. Our query should take a topic as a parameter, and based on the topic, it should search for comments that match the topic. We 'll take outer content, create an add and topic as the result. Let's start this query in our code and add it to the request body. We'll also provide the topic as the variable. Right now, we're only left to handling the response and the possible error after the fetch call. From the GraphQL spec, we know that the error result format is an array with objects with the key message and the string description of the error. Here's an example. Based on that, we're going to set our error state variable to response, errors, first, item, message. Also, based on this spec, we know that we'll get an object with a data key upon a successful call. Inside, we'll get a query root type and fields that we asked for. So I'm going to use set comments function. We press the data that comments. We also need to set loading to false in both success and error case. We are also going to use a JSON function on the response, which will set the content type header to application JSON so that the client twists the response string as a valid JSON object. One last thing here. We need a catch in case of unknown network errors. In the catch, we'll use set error and propagate the error that we got and we're also set loading to false. Another important point of the hook is that we actually need to call this function on initialization. For that, we'll use the use effect hook. We'll call it with an empty dependency array and we'll pass the fetch comments function. Last but not least, we need to return the object with our state. Now let's use this hook in the post component and see how it works. In this JSON, we'll use console log to inspect the result and in the next ones, we'll be working on adding a UI. Let's call the hook and pass a neural to the hasura instance that we created in the previous module. As a topic, we'll pass a slack. It's a post identifier that you can see in the blog squirrel. Let's add the console log below to see how it works. We should see the following in the console after the fetch call has been made. Since we don't have any comments related to dynamic routing in our hasura, the comments are usually empty. You can go to hasura console, add a few entries and open that post again. Next job, we implemented a massive portion of the commenting system in this lesson. You should be really proud of yourself. We have a custom hook, we covered integration of hasura and we saw comments patched from the database. In the next lesson, we'll implement a simple UI for the comments.