Creating reusable custom React Hooks
By: Paulo Levy
Tags: Firebase, JavaScript, React, React Hook, Functional Programming

Since React 16.8 you no longer need class components to work with stateful logic. The way to do it now looks like this:

The code above works perfectly on a functional component (previously referred to as ‘stateless functional component’) and that brings lots of new possibilities for the way we structure projects.

The most commonly used hooks are useState and useEffect. In case you are not familiar with any of those, I suggest you read the official documentation on React Hooks.

But it doesn’t stop there. To get the most out of this new feature we can write custom react hooks in order to reuse logic amongst components. Let’s check it out on a few real examples.

You can use the codes below on an existing project or create a new one by running 'create-react-app custom-hooks-project' on the terminal.

Creating an Infinite scroll with react hooks

Suppose you want to render a table with lots of entries. You probably don’t want react to render it all at once, resulting in a very long page where users may not even get to the bottom of it. One possible solution is to implement an infinite scrolling table, to render new entries as the user scrolls down.

Edit file App.js (gist)

App.js

The above code loads some fake data from the web and displays it in an HTML table. All the row elements are rendered at once, which is bad if you have a long list of items. To solve the issue, we could render 30 items at once and render 10 more each time the user hits the bottom of the page.

If we were to implement this logic on the App.js file and then need to reuse it on another component, there’d be code redundancy.

Thanks to React Hooks, we can implement the logic on a separate custom hook and use it wherever needed.

The naming convention to creating custom hooks is to start it with the word “use” for instance useCustomHookName. This is important for react to check for violations of rules of Hooks.

2. Create custom react hook file useInfiniteScroll.js (gist)

useInfiniteScroll.js

This created hook accepts 2 arguments:

start : The starting number of elements to be rendered.

: The starting number of elements to be rendered. pace: The subsequent number of elements to be rendered.

By default, they are set to 30 and 10, respectively. Meaning you can call the hook without passing any arguments and those values will be used.

The logic is pretty simple: the value returned by the custom hook (which will be the number of elements we'd like to render) is increased by the pace variable each time the user hits the bottom of the page.

M ake sure the inital number of elements rendered allows for vertical scrolling.

Now all that’s left to do is use the newly created react hook inside the App.js component. Replace App.js' previous code with the following:

3. Update file App.js (gist)

Updated App.js

You can run 'npm start' on the console to test the app. It should work as follows:

Infinite Scroll hook in practice

Creating a real-time firebase database entry listener

Let's make it more complex with this one. If you haven't tried Firebase's real-time database, I recommend doing so. They've made it really easy to set up a free online database and backend as service so you can focus on front-end development.

If you need help with the setup you can follow the steps on this link.

In case you don't want to create a database of your own and yet try this example, you can uncomment the data I've provided in the configs file.

Assuming you have a firebase account with a real-time database it's time to create the configurations file. But first, install firebase on your project by running 'npm install firebase --save' .

Create configs file database.js (gist)

database.js

This file enables connection to your database, and from now on each time you want to perform a database action on a file such as inserting new entries, editing previous ones, etc, make sure you import firebase from "./database.js" file and not from 'firebase' package.

With the database configured, you can now access some of its methods such as push, put, remove, etc… you can read the full documentation if you need help, for this example you will need 'push' to insert data to the database and 'on' to retrieve such data in real-time.

2. Create file useDatabaseEntry.js (gist)

useDatabaseEntry.js

When retrieving data from firebase, you get an object indexed by the unique keys firebase automatically generates. The problem is that the .map() function is available for arrays only. What this custom hook does is retrieve data from firebase and convert it to an array, so that is can be then easily be mapped to our table.

3. Edit file App.js (gist)

App.js

In the App.js file, there's a button to push data to firebase, and the useDatabaseEntry receives the desired entry as an argument and returns an array with the data from the entry.

The advantage is that you can now use this new hook to retrieve real-time data from any entry of the firebase database directly as an array, which makes it easy to be mapped to a table for instance.

If you want to practice, try clicking the button a couple of times to insert more data and make use of the useInfiniteScroll defined in the above example.

Here's the result: