How To Use React.js In Aurelia

I am rather smitten with Aurelia but it’s hard to deny the popularity of React. To avoid a situation where it’s React or nothing, to get the best of both worlds, we can use React inside of Aurelia.

In Angular, we would have done this using a custom directive. In Aurelia, we are going to be doing the same, but instead, we will be creating a custom element which achieves the same thing as an Angular directive, albeit in a more clean ESNext and Aurelia-like way.

Installing React

Before we proceed we need to make sure that React is installed. We can do this by installing it: npm install react --save — we also need to install the React DOM package as well for rendering our custom components: npm install react-dom --save

In the below code example we are going to create a custom element, which will pass data through to React and also has the added advantage of re-rendering itself when the data changes.

Create a custom element

For the sake of sticking with the demo, I recommend saving this file as “react-element.js” or honestly whatever you want to call it. The filename is irrelevant, I recommend sticking with this name for the sake of the article.

import React from 'react';
import ReactDOM from 'react-dom';
import {customElement, inject, bindable, noView} from 'aurelia-framework';

import MyReactElement from './components/my-react-element';

@noView()
@inject(Element)
@bindable('data')
@customElement('react-element')
export class ReactElement {
    
    reactComponent = {};
    
    constructor(element) {
        this.element = element;
    }
    
    render() {
        this.reactComponent = ReactDOM.render(
            ,
            this.element
        );
    }
    
    bind() {
        this.render();
    }
    
    /**
     * Data Changed
     * 
     * An automatic callback function when our "data"
     * bindable value changes. We need to rebind the React
     * element to get the new data from the ViewModel.
     * 
     * @param {any} newVal The updated data
     * @returns {void}
     * 
     */
    dataChanged(newVal) {
        this.bind();
    }
    
}

Creating a React component

For the above example, let’s create our React component. It will not do much, but it will work nonetheless.

Save the following file as my-react-element.js as per the above example and instructions.

import React from 'react';

export default class MyReactElement extends React.Component {
    constructor(props) {
        super(props);
    }
    
    render() {
        if (!this.props.data.length) {
            return null;
        }
        
        return (
            
                
                Hello, I am a React component being rendered inside of Aurelia.
                This file is located in: src/components/react-components/my-react-element.jsx and is being included from within src/components/custom-elements/react-element.js
                Let's loop through any provided data:
                
                
                {
                    this.props.data.map(item => {
                        return {item.name}
                    })
                }
                
            
        );
    }
}

MyReactElement.defaultProps = { data: [] };

Putting it together

The ViewModel

All the ViewModel does is supply our view using the React custom element with data.

Save this file as whatever name you like. For the purposes of this example, I recommend choosing react-example.js – so everything stays inline with the rest of this post.

export class ReactExample {
    
    someData = [];
    
    constructor() {
        this.someData = [
            {key: 'testkey', name: 'Dwayne'},
            {key: 'testkey2', name: 'Rod'},
            {key: 'testkey3', name: 'Todd'}
        ];
    }

}

The View

Okay, now that we have our ViewModel, we need our matching view. The name of the View HTML file needs to match the name of the above ViewModel Javascript file, not the class name. So if you saved the above as “react-example.js” – we will save this View as “react-example.html”

Source Code & Demo

You can download and view the source code here on Github. You can also view a demo of the code working here.