Easy apps with hyperHTML — 3, components and state
Tags: javascript, hyperhtml, tutorial, webdev
Published: 2019-05-29 14:20:32

## Moar about components and simple state management

[Version en español](https://medium.com/easy-apps-with-hyperhtml/aplicaciones-f%C3%A1ciles-con-hyperhtml-3-fc4a0503f498)

Part 3 written by {% user pinguxx %} {% user paritho %}

1.  [Introduction, wire/bind](https://dev.to/pinguxx/easy-apps-with-hyperhtml-1-31cc)
2.  [Events and components](https://dev.to/pinguxx/easy-apps-with-hyperhtml-2-hbi)
3.  **Moar about components and simple state management**
4.  [Wire types and custom definitions (intents)](https://dev.to/pinguxx/easy-apps-with-hyperhtml-4-38k3)
5.  [Custom elements with hyper](https://dev.to/pinguxx/easy-apps-with-hyperhtml-5-13hc)
6.  [Customizing my custom elements](https://dev.to/pinguxx/easy-apps-with-hyperhtml-6-1e73)
7.  [Testing!](https://dev.to/pinguxx/easy-apps-with-hyperhtml-7-5b9g)
8.  [Async loading, placeholder and a Typeahead with hyper](https://dev.to/pinguxx/easy-apps-with-hyperhtml-8-async-loading-5d96)
9.  [Handling routes](https://dev.to/pinguxx/easy-apps-with-hyperhtml-9-routing-59k0)
10.  [3rd party libraries](https://dev.to/pinguxx/easy-apps-with-hyperhtml-10-3rd-party-libraries-2n7b)


![](https://thepracticaldev.s3.amazonaws.com/i/zibxjb8q14x183bojg6q.jpeg)

In [part 2](https://dev.to/pinguxx/easy-apps-with-hyperhtml-2-hbi), we used hyper Components to create a table that can be sorted. Before we add to our table, let’s review the code we previously wrote.

{% stackblitz basics-table-5 ctl=1 %}

### Table components

Did you notice there are parts of the code we can reuse? If we refactor our code, we can use parts for other tables and it will be easier to maintain those parts instead of updating the entire table for every change. These parts are great candidates for such a refactor:

*   The main table definition
*   The header (row and columns)
*   Body (rows and columns)
*   Footer… well we don’t have a footer yet but we will add one just for fun

Let’s look at how we can change these parts to be more maintainable and reusable.

#### Table

First, let’s create a Table.js file and move most of the code there. We won’t need to use bind() in this file, instead we’ll export our Table.

{% stackblitz basics-table-5-1 file=Table.js %}

Next, let’s update index.js to import our table. This is where we’ll use the bind() function. Recall that bind() works on existing domNodes like document.body. Also note how we’re passing information to the Table: through an object in the constructor.

{% stackblitz basics-table-5-1 file=index.js %}

* * *

#### Header

Our Header class will extend Component as well.

Let’s first move the `<thead>` element of our table to render(), making it look like this:

{% gist https://gist.github.com/pinguxx/ef5d2208b6e9bfae2ed0df5c97a8657c %}

In this template we have onclick listeners attached to our `<th>` tags. Since we don’t want to manage the state in this class, we are going to dispatch a custom event called sort. This custom event will have some details about the sorting like the column we are sorting on and if it is ascending or descending.

We are going to add an update function as well. By using this function, we can be sure we’re always rendering with the current data. If the data changes in the parent, our header will receive the new data. It will look like this:

{% gist https://gist.github.com/pinguxx/0cda0ed391825536a7aaed93f9362e26 %}

Dispatch is a function provided by Component. It will create a custom event with a name based on the first parameter, and the details object based on the second parameter. This is a pretty useful function. Learn more about dispatch() in the [documentation](https://viperhtml.js.org/hyperhtml/documentation/#components-3). Our onclick event handler now looks like this:

{% gist https://gist.github.com/pinguxx/3d147792b8699f00e1cd93d4987506f4 %}

And here’s the complete Header class:

{% stackblitz basics-table-5-2 file=Header.js %}

Now let’s update Table to load the header component. Import again is our friend. Then, in place of the `<thead>` mark-up in the render, let’s use the Header class `${Header.for(this).update(this.state)}`.

Component.for its a utility that helps you create components in render(). Instead of creating the component somewhere else, you can create it right there in the function itself. Header.for(object) will then tie the header to the object passed, in this case our current table class, then call update to re-render the header with the state, this will passed on every render. We will use other ways to instantiate the modules later on. Read more in the [documentation](https://viperhtml.js.org/hyperhtml/documentation/#components-3).

Lastly, we will add an event listener called onsort to the table: `onsort="${this}"`. This function will listen to the sorting event we dispatched from the Header. We need to change the `onclick` function to `onsort`, and we’ll also simplify it a little. The information about the sort is coming in the event detail object. We can then sort the array like before and update the state of the table. Remember, we are passing this state down to the Header class.

{% gist https://gist.github.com/pinguxx/18ea81aa0ad2f18822877fbef037f07a %}

Let’s take a look at the full code to this point:

{% stackblitz basics-table-5-2 file=Table.js %}

* * *

#### Body

For our body component, let’s do the same thing — move the `tbody` from the render function of the Table to a new component called Body. Body will have its own render function; we’ll put the `tbody` code here:

{% gist https://gist.github.com/pinguxx/db5e9cb1e961fdd5544f99591c2666c8 %}

Despite being the component that renders most of our table, this component is actually pretty compact. Let’s see the full file:

{% stackblitz basics-table-5-3 file=Body.js %}

Notice the line:

`this.props = props;`

We’ll use this to pass data to the Body component. The information we pass will be the information shown in our Table.

Now, let’s update Table to load the Body component, using import just like before:

`import { Body } from './Body';`

In this case, let’s mix it up a little bit. Instead of Component.for, let’s create a new Body in the constructor. We don’t need to pass data on instantiation.

`this.body = new Body();`

With that, we have a table that will work correctly. It will sort, but our data is not really changing (adding or removing). But what if the data does change? We can add the update function inside Body to receive data, just like in Header.

{% gist https://gist.github.com/pinguxx/0cda0ed391825536a7aaed93f9362e26 %}

This way we always receive the latest data from the Table. Now, we call the update() function on the Body component directly:

`this.body.update(this.data)`

Let’s see how it looks.

{% stackblitz basics-table-5-4 file=Table.js %}

* * *

**Footer**

And as promised… we are going to add a little footer to our table. The footer will show the total number of records. Beside the html for the footer, there is nothing new in this class. Take a look:

{% stackblitz basics-table-6 file=Footer.js %}

We’ll update the Table component to load the Footer component. Let’s use Component.for and the update function since we always want to receive the latest data. Otherwise, our count of the items in the table will not be accurate.

`Footer.for(this).update(this.data)`.

{% stackblitz basics-table-6 file=Table.js %}

Aaannddd we are done! We have our simple table with simple state management: we pass data down and events up. We could have used a state management library, Redux or Flux. For our Table, we don’t really need to use anything more complex than what we currently have.

* * *

Before we move on to part 4, let’s explore a small library called [ProppyJS](https://proppyjs.com/). ProppyJS isn’t a state management library, but a library that allows us to compose properties. This is useful to compose props from various sources and use them in any component — in essence, we’re allowing ourselves a vast amount of freedom with our apps. With proppy, we could easily attach a redux store if we needed it later, when our component state gets more complex.

{% stackblitz basics-table-6-p %}

We created a prop factory and we use that p everywhere. It condensed our code a lot, and now the header is updating the sort directly. Let us know in the comments if you have questions about implementing ProppyJS.

* * *

We want these tutorials to be as awesome as they can be! If you have feedback, please be sure to leave it in the comments. Thanks for reading, and stay tuned for the next part where we’ll explore a powerful feature called “intents.” Intents will let us expand hyperHTML with custom definitions for our templates.