🚀  Manifold is joining Snyk! Read more in our announcement.

Clean Up Stateless Vue Components with Functional Components

The announcement of Vue v2.5 came with much buzz to the Vue community and many improvements to Vue. One of these is the improved support for functional components in Vue. In this article, we will be cleaning up Vue components without state and instances (this) with functional components.

Photo by StickerMule on Unsplash
Photo by StickerMule on Unsplash

What are Functional Components?

Functional components are an alternative to the widely used Vue components. They use either render functions or are JSX components without state and instance. This means they have no data property or an instance of this. Functional components are functions.

Functional components are cleaner and easier to render. This is how a simple functional component looks:

<a href="https://gist.github.com/christiannwamba/00d85ffb8851ec401952be8cd59e92e7#file-block1-js" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://gist.github.com/christiannwamba/00d85ffb8851ec401952be8cd59e92e7#file-block1-js</a>

Note: Props in functional components may not be specified, in which case all props are received from the component’s node.

When using functional components, the context argument is introduced to make-up for the lost state and instance.

One may wonder why we have children as well as slot. This is because context.children refers to all child elements of the node whereas `slots().foo` refers to all slots with the name foo, and `slots().default` refers to all child element except named slots. These give us the flexibility to choose ways to target child elements. Let’s look at a simple conversion from a stateful component to a stateless on using functional component.

Conversion from Stateful to Stateless

Let’s create a simple generic header, which can be used throughout a Vue instance. Headers are from h1 through to h6. From a stateful component perspective:

<a href="https://gist.github.com/christiannwamba/7a6399bdbd82dd23a0126f0c36f5f34e#file-block2-js" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://gist.github.com/christiannwamba/7a6399bdbd82dd23a0126f0c36f5f34e#file-block2-js</a>

See a codepen demo here:

<a href="https://codepen.io/codebeast/pen/LOreOJ" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://codepen.io/codebeast/pen/LOreOJ</a>

In our stateful header, the createElement() function is used to create the header passing it arguments of the level props and the $slots.default instance for any child node. Since we have no data from this component, let’s make this cleaner by making it a functional component, thereby eliminating all instances of this and introducing the context argument to handle props.

<a href="https://gist.github.com/christiannwamba/feefc104ad8c7c6fa2818b62c2da5f51#file-block3-js" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://gist.github.com/christiannwamba/feefc104ad8c7c6fa2818b62c2da5f51#file-block3-js</a>

See a codepen demo here:

<a href="https://codepen.io/codebeast/pen/yPEppM" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://codepen.io/codebeast/pen/yPEppM</a>

Notice how this.level is replaced with context.props.level and this.$slots.default is replaced with context.children.

Single-File Functional Components

From Vue v2.5, functional components defined by single-file components can have the functional attribute in the template tags. This denotes the component as a functional one, eliminates the need to specify the functional property in `<script>` and the component is treated outright as a functional component.

Also, functional components have CSS in scope as well as hot-reloading features. I built a simple Vue project using the webpack-simple template to show a sample functional component.

It is assumed that you have node and npm installed.

Vue ships with a wonderful CLI for building applications fast, using npm install Vue with:

npm install vue-cli -g

A new project with the webpack-simple template is created using:

vue init webpack-simple functional-component

A simple Vue project is created and the command:

npm run dev

serves the Vue project on a development server on localhost:8080.

In the project folder, we create a file named **Header.vue** in `/src/components/` and edit it to:

<a href="https://gist.github.com/christiannwamba/9f4c6dcc889ed04792cb7214328faa7b#file-block7-html" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://gist.github.com/christiannwamba/9f4c6dcc889ed04792cb7214328faa7b#file-block7-html</a>

This is our functional component. Note the absence of the props object? This is because the props object is passed explicitly from the components node. In App.vue located in `/src/` wipe all the data provided by our template and edit it to:

<a href="https://gist.github.com/christiannwamba/c3349ae8abdc999756f34bbce4a61ecd#file-block8-html" class="embedly-card" data-card-width="100%" data-card-controls="0">Embedded content: https://gist.github.com/christiannwamba/c3349ae8abdc999756f34bbce4a61ecd#file-block8-html</a>

This is our parent Vue template, the app is built here.

Now run `npm run dev`.

The browser displays:

The app can be styled anyway, either the component is styled and the scoped attribute is used on the style tags as seen above to ensure that the styling is scoped to solely the component in view.

## Conclusion

Functional components are used because they are lighter and cheaper to render by the browser. Instead of using JSX or render functions, they are stateless and have no instance. With the release of v2.5 of Vue, functional components can now possess scoped styling as well as hot-reloading features as we have seen in the simple demo above.

## About Manifold

[Manifold](https://www.manifold.co/) is the first independent marketplace for developer services and the easiest way to manage and share everything from JawsDB, a simple postgres database to Mailgun, an API that makes sending and receiving email dead simple.

> For more info visit manifold.co or follow us on twitter. This post is part of the Manifold Content program. [Want to write for us?](https://www.manifold.co/compose)

Recent posts

Related posts

No items found.