Last updated October 22, 2018

The most straight-forward way to use React in an existing site is to connect it directly to your Drupal 8 theme and then start writing React code.

In this tutorial, we will cover how to connect the React libraries and a custom React script to Drupal through the use of asset libraries in a custom theme. This includes:

  • Creating asset libraries that link external React and Babel JS libraries
  • Adding a .js file in your theme with React-specific code in it and adding it to an asset library
  • Modifying the HTML output by Drupal to contain a DOM element for React to bind to

By the end of this tutorial you'll know how to configure everything necessary to start writing React right into an existing Drupal theme.

Goal

Connect a "Hello, World" React application to a Drupal 8 Theme.

Prerequisites

  • Drupal 8.5.x installed and create 1 node using the Page or Article content type
  • Know how to create and edit a Drupal theme
  • Basic JavaScript, ECMAScript 5 or higher

Example code

Code for this example can be found in the Git repository at react-and-drupal-examples/hello-world.

How things connect

When adding React to a Drupal theme we need to:

  1. Use an asset library to add both the React JS library code and our custom JavaScript.
  2. Modify the HTML of the page by overriding a template file and adding a DOM element like <div id="react-app"> for our React application to bind to.

Set up a new theme

First, create a new theme.

  1. In your Drupal installation, go to /themes.
  2. Create a new theme folder called react_simple.
  3. Create a new *.info.yml file called react_simple.info.yml with the following contents:

    name: React -- Simple Hello World
    type: theme
    description: 'A theme that loads React JavaScript libraries, and a React application.'
    core: 8.x
    base theme: seven
    
  4. In Drupal UI, go to /admin/appearance and enable the theme React - Simple Hello World.

  5. Clear your cache in /admin/config/development/performance if necessary.

React Simple theme

Override the node template

We will add a markup container to a node template.

  1. Create a new folder called templates in /themes/react_simple/templates.
  2. Copy the node content template file at /core/themes/classy/templates/content/node.html.twig and save in your templates folder as node.html.twig.
  3. We will add following code to our theme's Twig file, near the end, near the {{ content }} tag.

    <div id="react-app">
    React app will load here.
    </div>
    <hr />
    Node content appears here:
    {{ content }}
    
  4. Clear your Drupal cache as needed.

Learn more about overriding template files.

Create a test node

If you did not already create some node content in your Drupal installation, create one using either the Article or Page content type. For the sake of demonstration, we will refer to this as /node/1 in your browser.

Once you save this node, you should see your node content displayed, along with "React app will load here.".

React app will load here.

Create a custom React script

We will add a custom React script to the theme.

  1. Create a folder called js: /themes/react_simple/js.
  2. Create a new file called index.js: /themes/react_simple/js/index.js.
  3. Add a Hello, World sample React script to your index.js file.
// Import not needed because React & ReactDOM are loaded by *.libraries.yml
// import React from 'react';
// import ReactDOM from 'react-dom';

// # Example 1: Simple Hello World code
ReactDOM.render(
  <h1>Hello there - world!</h1>,
  document.getElementById('react-app')
);

This is the simplest React script from the React website. For our purposes, the import scripts are commented out because we're loading the React library in the header of our webpage, so we do not need the import for those two libraries. The ReactDOM (i.e. virtual dom) will look for the react-app HTML element ID, and replace it with the HTML markup produced by your React code.

Add React libraries to theme

Now, for the fun part. Let's add React to the theme. We will use Drupal's asset libraries. (See Additional resources below for related tutorials on asset libraries in Drupal.)

  1. Create a new file in the theme folder (*.libraries.yml): /themes/react_simple/react_simple.libraries.yml.
  2. Add the following code to your react_simple.libraries.yml file.
react:
  version: 1.x
  header: true
  js:
    https://unpkg.com/[email protected]/umd/react.production.min.js: { external: true, minified: true }
    https://unpkg.com/[email protected]/umd/react-dom.production.min.js: { external: true, minified: true }
    https://unpkg.com/[email protected]/babel.min.js: { external: true, minified: true }
react-app:
  version: 1.0.0
  footer: true
  js:
    js/index.js: { preprocess: 0, attributes: { type: text/babel } }

This adds two React libraries to the registry of JavaScript, react and react-app, and also a standalone Babel interpreter so that the correct version of JavaScript code can be understood by the browser. Each library set is given a version number (which helps with in-browser cached JavaScript files). Notice that the react scripts will be placed in the header, and the react-app in the footer. Since the DOM element (div#react-app) needs to load, you can ensure that the HTML is available by placing the script in the footer. The third script (Babel) will allow us to use the most recent version of JavaScript.

Here is a breakdown of this file:

  1. We add the main minified React library and also the React virtual DOM. We indicate that these files are loaded from external sources, and minified.
js:
  https://unpkg.com/[email protected]/umd/react.production.min.js: { external: true, minified: true }
  https://unpkg.com/[email protected]/umd/react-dom.production.min.js: { external: true, minified: true }
  https://unpkg.com/[email protected]/babel.min.js: { external: true, minified: true }
  1. We attach our custom React script. Drupal will not aggregate this file (preprocess: 0). This makes it easier to view changes to your JavaScript file when you refresh the page. When you put your code into production, you can include your custom React script in your aggregated JS files. We also use a different type of script rendering using the attributes options. Instead of text/javascript, we use text/babel. When we do this, the script will be processed by the Babel script we loaded in the header. This translates some of the ES 6 JavaScript code into a version that all browsers will read.

Note: This is not the most commonly used way of configuring React. We will learn a more common set up in the tutorial, Create a Fully Decoupled React Application. However, what we have presented here will get you started with loading React in a Drupal page.

js:
  js/index.js: { preprocess: 0, attributes: { type: text/babel } }

Add the JavaScript libraries to your node.html.twig file

Our last step. The libraries that we declared in *.libraries.yml, react and react-app need to be connected back to the theme. Edit the node.html.twig file again and add the following below the existing line {{ attach_library('classy/node') }}.

{{ attach_library('react_simple/react') }}
{{ attach_library('react_simple/react-app') }}

Learn more about asset libraries.

See that React is loaded (troubleshooting)

  1. Clear your cache one more time to make sure the theme and libraries are updated in the registry.
  2. Reload your node page in the browser.
  3. You should see the text "Hello there - world!" where "REACT RENDERS HERE" was. If so, React has loaded successfully.
  4. Edit your JavaScript file and refresh. If you are not seeing your changes, make sure your browser is not caching your JavaScript files and clear your Drupal cache. In Google Chrome, you can go to the Dev Tools: Network Tab > Disable cache.

Disable cache highlighted in Google Chrome

Recap

In this tutorial we created a new custom Drupal theme, and a simple "Hello, World" React application and incorporated it into our theme. We learned about using asset libraries to attach external JavaScript libraries like React and Babel. We modified the node.html.twig template file in order to include our asset libraries.

Further your understanding

  • Try to add React to a block or menu.
  • See if you can add the Babel translator for ES.Next.

Additional resources