Phoenix v1.1.2 and React.js

Kind of like chocolate and peanut butter!


Previously, installing and using React.js on a Phoenix application required ripping out brunch and replacing it with something like Webpack to get everything working, but the process has been improved significantly with the introduction of Phoenix v1.1.2 which includes a new version of Brunch that works with npm. We’ll walk through creating a new project using Phoenix v1.1.2 and getting a basic React component working and rendering on our main page.

Current Versions

Phoenix: v1.1.4

React: v0.14.6

ReactDOM: v0.14.6

NPM: 3.6.0 (Very important, this process will not work with NPM 2.x; you need to use 3.x)

NodeJS: v5.6.0

Brunch: v2.1.x, v2.2.x, v2.3.2+(v2.3.0 breaks with error messages about NODE_ENV being undefined, so make sure you’re using one of the versions I listed!), v2.4.x

Creating Our Project

We’ll start by creating our Phoenix project before we do anything else. This will require us having Phoenix v1.1.2+ installed via local hex before anything else.

$ mix local.hex
$ mix archive.install

If you’ve installed Phoenix before, it will ask you if you want to override any existing packages. Just say yes here. Next, we’ll create a new Phoenix application:

$ mix reactpx

Go ahead and answer yes to fetching/installing dependencies. We’ll be needing them this time! Now, move into that directory and we’ll move on to installing our NPM dependencies.

$ cd reactpx

Installing Our NPM Dependencies and Configuration

We’ll start off incredibly simple and just install react, react-dom, and we’ll also need a babel preset for JSX templates via React:

$ npm install --save react react-dom babel-preset-react

After this is complete, we’ll need to modify our brunch-config.js file in the root directory of our Phoenix application to support the new modules we installed. First, look for the section regarding “plugins”, and then the sub-object for “babel”. Here we’re going to add an array of presets that we want babel to use:

plugins: {
babel: {
presets: ["es2015", "react"],
// Do not use ES6 compiler in vendor code
ignore: [/web\/static\/vendor/]

We also need to whitelist the installed npm modules under the npm configuration section so that brunch knows we’re going to use “react” and “react-dom”:

npm: {
enabled: true,
// Whitelist the npm deps to be pulled in as front-end assets.
// All other deps in package.json will be excluded from the bundle.
whitelist: ["phoenix", "phoenix_html", "react", "react-dom"]

Save this file, and run brunch’s build command just so that we’re sure everything is golden (technically, the first time you start up the Phoenix server this will happen anyways, but if you already started your server up this won’t happen unless you modify something, which we’ll do later):

$ brunch build

Important Note About NPM Versions

This tutorial assumes you are using NPM 3.x. If you’re using NPM 2.x you’re going to hit issues attempting to build everything together, as has been suggested by a few people. For more information, please reference Special thanks to Matt Widmann and Fabio Akita for pointing this out!

Writing An Example Component

Now let’s set up our Phoenix app so that we can add a small Hello World react component on our page. Open up web/templates/page/index.html.eex and replace the contents of the whole file with:

<div id="hello-world"></div>

Finally, you’ll want to add the following snippet of code to the bottom of your web/static/js/app.js file:

import React from "react"
import ReactDOM from "react-dom"

class HelloWorld extends React.Component {
render() {
return (<h1>Hello World!</h1>)


It Works!

Start up the server if you haven’t already:

$ iex -S mix phoenix.server

And on the main page, you should see something like the following:

Our React.js component loaded into our main app (also showcasing the React Chrome extension)

Congratulations! You now have a working React.js component inside of a Phoenix application with no requirement of swapping out Brunch for Webpack or any other extra work! Enjoy! If you want to just check out the repo for this as a starting point, you can find it at: