Using JSX with Vue
Tags: vue, javascript, webdev
Published: 2019-11-14 14:33:07

---
title: Using JSX with Vue
published: true
date: 2019-11-14 14:00:08 UTC
tags: vue,javascript,webdev
canonical_url: https://blog.logrocket.com/using-jsx-with-vue/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/g8kv7rx2mcbg7c9uepo4.png
---
**Written by [Anjolaoluwa Adebayo-Oyetoro](https://blog.logrocket.com/author/anjolaoluwaadebayooyetoro/)**✏️

The common way to build Vue apps using templates. It is not as common to build Vue apps using render functions and JSX. In this tutorial, we will learn what render functions are and how they work. We will also take a look at what JSX is and why you might want to use it in your Vue project.

## Prerequisites:

The following is required to follow along with this tutorial:

- [Node.js 10x](https://nodejs.org/en/download/) or higher and [Yarn](https://yarnpkg.com/lang/en/) / [npm 5.2 or higher](https://www.npmjs.com/get-npm) installed on your PC
- Basic knowledge of JavaScript, [React](https://reactjs.org/docs), and/or [Vue](https://vuejs.org/v2/guide) fundamentals
- [Vue](https://vuejs.org/) CLI installed on your PC, which you can do with the following command using yarn:

```jsx
yarn global add @vue/cli
```

## Getting started

### What are render functions?

A [render function](https://vuejs.org/v2/guide/render-function.html) is any function that returns a virtual DOM, they are what template code gets compiled to during the build process. The compiled code returns a virtual DOM which Vue processes to generate the actual browser DOM accordingly.

Render functions are closer to compiler alternatives than templates or JSX, they leverage on the `document.createElement()` Web API method to create HTML documents.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

### How do render functions work?

A typical render function looks like this:

```jsx
render (createElement){
 return createElement( 'div', {}, [....]
)}
```

The `createElement` method takes in three arguments:

- A render element, which can be an HTML tag name or a component
- An object that can contain data objects such as attributes, props, DOM props, styles, classes, and event handlers
- A child argument that can either be an array of children nodes, a single child node or plain text

The `createElement` parameter in render functions is often written as `h` to denote Hyperscript as [explained](https://github.com/vuejs/babel-plugin-transform-vue-jsx/issues/6#issuecomment-232994673) by [Evan You](https://twitter.com/youyuxi) — the creator of Vue.

Hyperscript stands for the script that generates HTML structures and helps create markups with JavaScript. The render function above can be rewritten like this:

```jsx
render (h){
 return h( 'div', {}, [....]
)}
```

![rendering process](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2019/11/renderingprocess.png?resize=1024%2C908&ssl=1)<figcaption id="caption-attachment-9794">A visual of the rendering process</figcaption>

## The Virtual DOM

According to [Evan You](https://twitter.com/youyuxi):

> The Virtual DOM is a lightweight representation of what the actual DOM should look like at a given point in time

Vue creates a Virtual DOM that keeps track of all the changes made to the real DOM and on every data change Vue returns a new Virtual DOM, it then compares the old virtual DOM to the new one and checks for specific changes and makes adjustments in the real DOM.

The process of comparing and checking changes between the old and the new Virtual DOM is referred to as [diffing](https://en.wikipedia.org/wiki/Diff).

This [mini-app](https://template-explorer.vuejs.org/) helps explore the Vue templates and render functions, you can learn more about render functions in Vue and the Virtual DOM [here](https://dev.to/bnevilleoneill/accessing-the-virtual-dom-using-render-functions-in-vue-js-5fh5).

## What is JSX?

JSX is an [XML](https://www.w3schools.com/xml/xml_whatis.asp)-like syntax extension for writing JavaScript. It’s a syntactic abstraction of render functions. It was built by [Facebook’s engineering team](https://opensource.facebook.com/) and originally intended to be used in building React apps in a more concise and elegant way.

JSX, similar to Vue templates, get compiled to render functions under the hood at build time.

## Why you might want to use JSX in your Vue project

- It makes no assumption about how your code should look or be processed. There is no defined way to write JSX
- JSX helps prevent cross-site scripting attacks because you can never inject code that is not explicitly written in your application, everything is converted to a string before being rendered
- JSX is dynamic. It gives you the power to do whatever you want to as it gives access to the full programmatic powers of JavaScript
- There is no registration of imported components, you can make use of them on the go
- It couples logic and markup together, you don’t have to write markup separately from the JavaScript
- Several components can be written in a single file as opposed to templates where you have to write every component in separate files
- JSX gives access to the spread operator, it makes things, like passing an object as props, easier

## Common Vue template features and their JSX implementation

### Conditionals (v-if)

#### Template implementation

```jsx
<template>
   <div v-if="user.age > 18">
      Welcome, {{user.name}}
    </div>
</template>
```

The block of code above displays a user’s name if the user’s age is greater than 18.

#### JSX implementation

```jsx
export default {
....
  methods: {
      checkStatement(){
        if (this.user.age > 18) {
           return <div> Welcome, { this.user.name }</div>;
        }
      }
    },
    render(){
      return(
        {this.checkStatement()}
      )
    }
}
```

In JSX, the condition to check for a user’s age is wrapped in a function housed inside the Vue method instance and then the function is invoked in the render method.

### Loops (v-for)

#### Template implementation

```jsx
<template>
  <div v-for="item in items" :key="item.id">
      {{ item }}
  </div
</template>
```

The v-for directive executes a block of code a number of times. In the code above we use the v-for directive to render a list of items in an array.

#### JSX implementation

```jsx
render(){
  return(
    {this.items.map(item => {
        return (
           <div> {item} </div>
          )
      }
  )}
```

In JSX, the items in an array can be mapped over, using the ES2015 `.map()` method.

### Events(v-on)

#### Template implementation

```jsx
<template>
    <div>
      <button v-on:click="handleButtonClick()"> click me</button>
    </div>
</template>
<script>
export default {
  methods: {
      handleButtonClick(e){
          e.preventDefault();
          alert('button clicked')
        }   
    }
</script>
```

The `v-on` directive listens to DOM events and triggers a function that performs a defined operation. In the code shown above, a click of the button triggers the `handleButtonClick()` function which displays an `alert()` dialog box.

#### JSX implementation

```jsx
export default {
  methods: {
      handleButtonClick(e){
          e.preventDefault();
          alert('button clicked')
        }   
    },
  render(){
    return(
    <div>
       <button onClick={this.handleButtonClick}> click me</button>
    </div>
    )
  }
}
```

### Interpolation (v-html)

#### Template implementation

```jsx
<template>
  <div>
     <div v-html="rawHtml"> </div>
  </div>
</template>
<script>
export default {
    data () {
      return {
        rawHtml: "<h1> This is some HTML </h1>",
      }
    }
}
</script>
```

v-html is used to set elements `innerHTML`, the code above sets the `innerHTML` of the div to the content of `rawHtml`.

#### JSX implementation

```jsx
export default {
    data () {
      return {
        rawHtml: "<h1> This is some HTML </h1>",
      }
    },
    render(){
        return(
          <div>
            <div domPropsInnerHTML={this.rawHtml}> </div>
          </div>
        )
      }
}
```

`domPropsInnerHTML` attribute performs the same task as `v-html` , it sets the content of the div to `rawHtml`.

### Importing components

#### Template implementation

```jsx
<template>
  <div>
    <NewComponent/>
  </div>
</template>
<script>
import NewComponent from "NewComponent.vue";
export default {
  data () {
    return {
      components:{
        NewComponent,
      },
</script>
```

#### JSX implementation

When using JSX there’s no need to register a component after importing it, you can just use it directly.

```jsx
import NewComponent from 'NewComponent.vue'
....
  render(){
    return(
     <div> <NewComponent/></div>
    )
  }
```

## How to set up a Vue project with JSX

For this section, we will be building a trivial app that displays a little bit of information about selected countries.

Create a new project

```jsx
vue create vue-jsx
```

Install the dependencies needed to make use of JSX in your project using yarn:

```jsx
yarn add @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props
```

Configure your babel file to use the presets for JSX by including the following in your `.babelrc` or `babel.config.js` file, located in your project root directory:

```jsx
{
  "presets": ["@vue/babel-preset-jsx"],
}
```

The `@vue/babel-preset-jsx` preset enables you to use the [JSX presets](https://github.com/vuejs/jsx/tree/dev/packages/babel-preset-jsx) made available by the Vue team.

Vue automatically injects `h` which is short for `createElement` in every method, so you don’t have to always declare `h` as a parameter in your `render()` function.

## Testing out our Vue-JSX app

To test it out, replace the content of your `HelloWorld.vue` file in `src/components` folder with the following:

```jsx
<script>
export default {
  data () {
    return {
      countries: [
        {
          name: 'Nigeria',
          description: "Nigeria is a large country that has a varied topography. It is about twice the size of the U.S. state of California and is located between Benin and Cameroon. It is the most populated country in africa"
        },
        {
          name: 'USA',
          description: "The United States of America (USA), commonly known as the United States (U.S. or US) or America, is a country comprising 50 states, a federal district, five major self-governing territories, and various possessions."
        },
        {
          name: 'China',
          description: "The People's Republic of China, simply known as China (Chinese:中国, pinyin: zhōng guó)is located in East Asia. It is the world's most populous country, with a population of around 1.404 billion. It is a unified multi-ethnic country with the Han nationality as the main nation."
        },
        {
          name: 'Argentina',
          description: "Argentina is a vast country located in the southern part of South America. The eighth largest country in the world, it is the second largest country in South America after Brazil, and it's about one-third the size of the United States. Argentina is bordered by the Andes Mountains and Chile to the west."
        },
         {
          name: 'Cameroon',
          description: "Cameroon is sometimes described as 'Africa in miniature' because it exhibits all the major climates and vegetation of the continent: mountains, desert, rain forest, savanna grassland, and ocean coastland. Cameroon can be divided into five geographic zones."
         },
         {
          name: 'Somalia',
          description: "With a land area of 637,657 square kilometers, Somalia's terrain consists mainly of plateaus, plains and highlands. Its coastline is more than 3,333 kilometers in length, the longest of mainland Africa and the Middle East. It has been described as being roughly shaped like a tilted number seven."
        }
      ]
    }
  },
  props: {
    msg: String
  },
  methods: {
    //where you write methods or functions used in your component
  },
  render () {
    return (
      <div>
        <div class="content">
          <h1>Hello, { this.msg } </h1>
          <main class="country-wrapper">
            {
              this.countries.map(country => {
                return (
                  <div class="country-container">
                    <h3 class="country-name ">{country.name}</h3>
                    <article class="country-description">{country.description}</article>
                  </div>
                )
              })
            }
          </main>
        </div>
      </div>
    )
  }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.content{
  width: 100%;
  .country-wrapper{
    width: 100%;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    .country-container{
      display: flex;
      flex-direction: column;
      text-align:start;
      margin: 1em;
      padding: .5em;
      width: 28%;
      height: 12em;
      border: .08em solid #c4c4c4;
      .country-name{
        margin: 0;
        margin-bottom: 1em;
      }
    }
  }
}
</style>
```

You should get a result similar to this:

![vue.js test app](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2019/11/vuejstestapp.png?resize=730%2C354&ssl=1)

## Conclusion

We’ve seen how render functions work and how to set up a Vue project to use JSX, check out the repository to this article on [GitHub](https://github.com/Jolaolu/jsx-in-vue). To learn about more awesome things you can do with Vue.js, check out the [documentation](https://vuejs.org/v2/guide/render-function.html).

* * * 
**Editor's note:** Seeing something wrong with this post? You can find the correct version [here](https://blog.logrocket.com/using-jsx-with-vue/).

## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *
The post [Using JSX with Vue](https://blog.logrocket.com/using-jsx-with-vue/) appeared first on [LogRocket Blog](https://blog.logrocket.com).