How to use React with Drupal
React.js is a very popular JavaScript framework created by Facebook. It allows you to build beautiful, interactive and fast interfaces, with which users will fall in love. Drupal, on the other hand, is a fantastic CMS with you can build small, medium and huge websites.
Sometimes you want to pair the two frameworks together - offer sophisticated Drupal backend, and a slick, quick frontend based on React. That is when Drupal and React can come together.
In this post, I will explore various methods of combining the technologies.
Headless Drupal vs. embedded React
The primary choice you have to make when using React with Drupal is whether you want to use a "headless Drupal" approach where Drupal is only in the backend and React is the only interface user ever sees or whether you just want to add a React app to the Drupal website rendered by the Drupal templating engine. Let me elaborate.
Headless Drupal with React frontend
In a headless scenario, Drupal serves as a backend for a frontend application built in React. The systems are entirely separate and communicate via HTTP - eg. REST of GraphQL.
This option is best if you want to:
- Create a Progressive Web App (PWA) for users on mobile devices.
- Create a single page app that stores data in Drupal
- Create an easy to use the access point to a subset of a big system built on Drupal. Say you have local agents who visit local stores and send screenshots of the merchandise display. They might need only an one easy to use interface without the complexity of your complete CRM of managing stores, which the office uses
- Create a smaller website that just pulls some data off of a big website, e.g. only displays news from one section of a huge news magazine.
How to create a Headless Drupal app
If you chose headless Drupal, you then build a separate React application which communicates with the backend via HTTP requests, just as you would with any backend system. React then does not really care what is in the backed. It only needs to be able to use the exposed API.
Facebook prepared a fantastic boilerplate React project to help you start.
When the React app is running, you then create endpoints in Drupal, which serve as data sources for your React app. Drupal 8 is a fantastic piece of software and comes packaged with a full REST API. You can find documentation on Drupal Rest API documentation page. Specifically, have a look at the REST UI module which enables you to create clean configurable endpoints for entities.
We wrote a great post about setting up REST endpoints for a JavaScript application.
If you prefer to use GraphQL, there is a GraphQL module which is under active development and allows you to build GraphQL endpoints.
If headless Drupal is what you are after, it is also worth checking out an example headless project: the ContentaCMS, which is an entirely headless implementation of Drupal with popular frontend frameworks. The React implementation can be inspected here.
React app embedded in Drupal
Quite often you don't need a full headless implementation, but just want one or two highly interactive elements on a few pages of your website. It might be a very complicated form with many steps which works nicer without a page reload or a different UI element which is highly interactive and will work much nicer done in JavaScript.
In that case, it makes much more sense to use React.js to create a component and embedded in a page that is served by Drupal. This way you can use all the Drupal greatness everywhere else, in example registration, rendering of fields, views etc.
How to embed a React app in Drupal
For starters, you will add React library to your website, just like you would add any other js library (e.g. a jQuery or some other library for a slider or gallery). Depending on whether the script is required on every page, or is it part of a theme or a module, there are various ways in which you can add a js library to the website. I will not go to details, because there is a lot of good documentation here:
1. https://www.drupal.org/docs/8/api/javascript-api/add-javascript-to-your-theme-or-module
and
2. https://www.drupal.org/docs/8/theming-drupal-8/adding-stylesheets-css-and-javascript-js-to-a-drupal-8-theme
A quick method, that is not recommended, but will work for testing purposes, is to just add the script tags to html.html.twig in your template:
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
and your own script with the app.
<script src="/paht/to/my/scripts/myreactapp.js"></script>
One caveat of an embedded app is that the only language you can use is Javascript. You can use neither JSX, nor TypeScript, which you might use when you create a headless app. This is because in a complete react app, Webpack or Babel transpile JSX or TypeScript into JavaScript. Here in our example, for the sake of simplicity, we are not using these tools.
Tip: To be able to use JSX you would have to use Webpack first to compile your JavaScript file and then add it to Drupal. A good approach then would be to use the create-react-app repo to start and then just copy over the resulting js file created after transpilation and embed that. You would then not need to embed react.js separately because it is already bundled in transpilation. Setting this up, however, so that auto refresh would work and the file would be copied to Drupal, is a bit more complicated and therefore we are skipping it.
Coming back to our example, the first thing to you have to create is an HTML tag in your markup in which the React app will live. It can be a div rendered in a block or by a custom controller on a separate route.
<div id="myreactapp" />
In myractapp.js create your app.
ReactDOM.render(
React.createElement(MyApp, {title: 'Hello World!'}),
document.getElementById('myreactapp');
);
Done! You have a react app embedded in a Drupal page. You can get data for it from a REST API like you would in the Headless example, or you can use the drupalSettings global for your initial data set.
function Welcome(props) {
if(props.isfront == true) {
return <h2> Welcome on front page<h2>
}
else{
return <h2> Welcome on another page </h2>
}
ReactDOM.render(
React.createElement(Welcome, {isfront: drupalSetting.path.isFront}),
document.getElementById('myreactapp');
);
Just remember that if you ever want to save changes to any data in Drupal, you still need to create an endpoint and push the changes there.
That is it! Combining React and Drupal is as easy as pie.
Enjoy!