In this lesson we will start to create a terminal React application with react-blessed
, which is a custom renderer for React. If you already know how to use React with the DOM, then you should be able to leverage a lot of what you already know to build an app for the terminal.
Elijah Manor: [0:00] From the terminal, let's create a new folder called devdash, and then immediately navigate to the new folder with $_. Once inside the new folder, we'll create a new package.json file with npm init, passing the dash -y flag, to auto answer "yes" to all the prompts.
[0:19] Now, let's start installing the necessary dependencies for our react-blessed app. We'll npm install react blessed and react-blessed. Then, we'll install some Babel dependencies for our React environment. We'll npm install @babel, and then we'll use dash brace expansion to install Babel core, Babel register, Babel preset-env, and Babel preset-react.
[0:46] Now, that our dependencies are installed, we'll quickly create an index.js file and a dashboard.js file. At this point, you can open up your favorite code editor. In this case, I'll open VS Code at the current directory.
[1:01] First, let us open the package.json file and create a start script of node index. That'll let us later to be able to start our app with npm start from the command line.
[1:13] Now, inside our index.js file, we'll register our application with Babel and add two presets of Babel preset-env, which is a smart preset, letting us use the latest JavaScript and Babel preset-react, which includes plugins to support JSX.
[1:31] Now, that our Babel environment is all set up, we can require our actual React dashboard. Let's switch over to our dashboard.js file, where we'll import React from "react," import blessed from "blessed," which is the low-level terminal interface for node JS. Then, import the render function from "react-blessed," which is a custom React renderer for the terminal.
[1:58] Now, we can start focusing on our app react component. The underlying blessed module defines a set of widgets that can be rendered through react-blessed using lowercase tag titles. We'll use the box element and return "Hello World!" You can think of box like a div when using react DOM.
[2:18] Now, let's create the blessed.screen interface and give it some settings of autoPadding, that gives child elements some border and padding, smartCSR which will attempt to perform change-scroll-region optimizations if needed, and a title.
[2:37] In order to exit we'll listen to a set of key events, Escape Q and Ctrl C. If one of those combinations is pressed, we'll exit the process with zero. Then, we'll create a component and render the app component to the screen. This step is similar to what you would do with ReactDom.render.
[3:02] Now, let's run our app from the terminal. We'll type npm start, and there's our "Hello World!" Not very exciting, but it's to start. We'll Ctrl C into the app and switch back to our code and give it a little bit of style. Let's add a few props.
[3:20] First, let's adjust the top to the center of the screen. Make the left also be center. Give it a width of 50 percent and a height of 50 percent as well. Then, we'll give it a border and change the type to line.
[3:34] Then, much like you would with ReactDOM, you could add a style using the style prop for finer control. In this case, we'll change the borders foreground color to blue.
[3:45] Now, if we come back to our terminal and start the app will see a centered box with a blue border. Let's exit the app again and this time make it a bit more dynamic.
[3:56] We'll create a dateTime variable and set it to the current date using toLocaleString, doing some basic formatting for the en-US locale. We'll set month to long, day to numeric, year to numeric, hour to two digits, minute to two digits, and use the 12-hour format.
[4:19] Now, instead of "Hello World!" we will replace that with a string template of "Today is" and render the dateTime variable. If we come back to the terminal and run our app now, we'll see a centered box, but with today's formatted date.
[4:34] Before we wrap up, I want to show how we can leverage react hooks inside our component to auto update the contents of our box. To do this, we'll add a counter. Down in our template string we'll add "Counter is ${count}. Then, we'll come up and define count and setCount from React.useState, initializing the value to zero.
[4:58] Then, we'll create a new timer variable and assign it to React.useRef. We'll use this to keep track of the current timer. Now, we'll use React.useEffect and assign the current timer to the setTimeout.
[5:13] We'll increment the count by one after one second has occurred. Then, to clean up after ourselves, we will return a function that clears the timeout if there happens to be one queued up.
[5:24] Finally, we'll want to make sure we add count to the dependency array, so the useEffect will update when the value of count changes. Now, if we go back to our terminal and start our app, we'll see the current date and time along with a counter that is updating after every second.
Phil, no it's not necessary in this case. If I wanted to pull out a custom useInterval hook then it gets really complicated. I simplified that whole bit in the next lesson.
Great, thanks.
Curious about the useRef for the timer. Is it really necessary in this instance?