This video is available to students only

Creating a React hook and fetching the comments

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.

In the previous lesson, we introduced a sample blog application that will be our use case for a commenting system. We saw a pages/posts/[slug].tsx file which contains a Post component. This component is responsible for rendering posts' content and details, and that's where we'll add a comments section and a form to add a new comment.

What should we do there? 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 comments that have topic set to dynamic-routing.

Note: This course assumes a basic understanding of React hooks — we will work with useEffect and useState hooks, and we'll create a custom one. If you want to revise your knowledge, we recommend checking out the officialReact docs.

Fetching the comments — requirements#

Let's open the [slug].tsx file and list what should happen there:

  1. On component load, we need to fetch comments added for a particular blog post from our Hasura instance.

  2. We need a few state variables to store information:

    • comments — at first, it's an empty list, which we 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 when fetching comments. By default, it will be null. If an error occurs, we'll set it to a string with an error message.

Let's write it down to help us visualize it in the code:

We could keep the fetching comments logic and state variables in the[slug].tsx file, and that would be totally fine. However, we will extract it into a separate custom hook, which will let us test the hook separately and reuse it in other components.

Implementing the hook#

A note fromReact docs on implementing custom hooks:

Unlike a React component, a custom Hook doesn't need to have 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 a glance that the rules of Hooks apply to it.

As hooks should have use prefix, and our subject is comments, we will call our hook useComments. Let's create a new file in the lib/ directory —useComments.ts.

Instead of going straight to writing implementation details, we'll 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 the ideal API is, and how we'd like to use it.

Let's start from something that is kind of the base of our commenting system — aComment 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:

Notice that created_at is typed as a string. It's because we get an ISOString from a GraphQL API. It's not being transformed into JavaScript'sDate, even though its type is timestamptz! in the schema spec:

GraphQL comes with default scalar types like Int, Float, String,Boolean, and ID, but it also allows defining custom scalar types.timestamptz! 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 Data type.

However, most popular GraphQL clients does not currently have a way to automatically interpret custom scalars, so there's no way to automatically reverse the serialization on the client.

As we have the Comment type, let's write down the hook function signature. Our hook will take two arguments:

  • hasuraUrl — an 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.

  • topic — an identifier of content, e.g., "my-blogpost-about-cats".

The hook returns an object, and I'll call its type UseCommentsResult.

We use declare keyword to tell the compiler about types before we write any implementation.

Now, let's create UseCommentsResult type. What information do we need from the hook?

  • Most importantly, comments — an 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 implementation details now.

Implementation details#

Firstly, let's declare all the state variables that we mentioned before:

Start a new discussion. All notification go to the author.