Extract a `react-blessed` Component and Add the `useInterval` Hook

Elijah Manor
InstructorElijah Manor

Share this video with your friends

Send Tweet
Published 2 years ago
Updated 2 years ago

Currently most of the code for our React Terminal Dashboard is all in one big file. This can become a problem as we continue to build the dashboard as it can hard to managed. So, we'll move out each section of our dashboard (which is just one at the moment) into their own React component. Along the way, we'll refactor a useEffect/setTimeout to leverage the useInterval custom hook.

Elijah Manor: [0:01] Here we have code for a React terminal app. If we go to the terminal and run npm start, it'll pick up the app and show the date and time, switching the font every second or so. Currently, most of the code is all in one big file. The problem is that as we continue to build this app into a dashboard, this will become very hard to manage.

[0:25] Let's move out each section of our dashboard, which is just one at the moment, into its own React component. We'll make a components folder in our root and create a Today.js component file. We'll copy most of the dashboard.js code and paste it into our Today.js file.

[0:48] Coming back to our dashboard file, we'll no longer need things specific to the Today component, like figlet for ASCII art, or the FONTS array, or most of the logic inside the app component. Even the JSX can be replaced. All is really needed is a reference to our new Today component.

[1:08] Let's go import that up at the top of the file, import Today from './components/Today'. One last thing, let's go ahead and pass an updateInterval prop to our Today component of 1,000 milliseconds.

[1:26] Now, let's clean up our Today file. This file doesn't need to concern itself with blessed or render directly, since those are now handled by the dashboard, but we will need to export our new Today component to be used by the app. We'll export default function and rename this to Today, and accept our updateInterval prop, initializing it to 1,000 milliseconds, if the consumer doesn't pass the value.

[1:55] Instead of using setTimeout, I eventually want to convert this to setInterval. At least to start with as we fetch data for our various dashboard widgets. However, there is a weird bug that can happen with setInterval and react.useEffect. The issue is described in detail on Dan Abramov's blog with a running example of showing the bug.

[2:17] The gist of it is, if the code is rendered too frequently, the setInterval could get cleared before it has a chance to trigger. This probably won't be a problem in our app, but to be safe, let's switch to another module written by Donovan West that takes into consideration the problem and npm install @use-it/interval.

[2:42] Now, at the top of the file we'll import useInterval from '@use-it/interval'. Then in our component we'll useInterval() passing in a callback and our updateInterval(prop).

[2:59] The contents of the callback will just be setFontIndex where we'll increment the value of fontIndex. Now, we could remove our react.useEffect, and the code is a bit more streamlined, and set up for future enhancement.

[3:15] You may notice that the ESLint plugin doesn't like us too much at this point with our updateInterval prop. By default, the recommended rules for the ESLint React plugin we're using includes a rule to enforce react/prop-types, which you may or may not want to use.

[3:32] Let's go to our ESLint configuration file and turn off this rule. We'll come down to the rules section and make a new entry for react/prop-types and tell it to turn off this rule. If we save our file and come back to our Today component, it will no longer give us an error.

[3:52] We should be able to come to our terminal again and npm start, to kick off our app. It still works. This time the code is a bit better organized and ready for future enhancement. Now that we're passing down an updateInterval prop, we can adjust that to something smaller, like half a second, which will override the default value. If we rerun our app, the font choice will update much quicker.