Adding React to a Phoenix project should be pretty straightforward, according to the docs, but it gave me some trouble, and I’m not the only one

Things change pretty fast, especially at the intersection of Elixir and JavaScript. So, as at the end of 2016, here is how to get React working with a Phoenix application.

Start with a new Phoenix project;

mix phoenix.new hello_react

mix ecto.create

mix phoenix.server

Open up web/templates/page/index.html.eex and replace the entire contents with this;

<div id="react-target">
  <h1>No react here</h1>
</div>

When you reload the page, you should see that message below the default Phoenix header.

Next, let’s get some javascript code running, as per the instructions in the Phoenix documentation

Now, open up web/static/js/app.js and add this at the bottom of the file;

export var App = {
  run: function(){
    console.log('javascript running')
  }
}

In web/templates/layout/app.html.eex find this line;

<script src="<%= static_path(@conn, "/js/app.js") %>"></script>

…and add this below it;

<script>require("web/static/js/app").App.run()</script>

Now, when you reload the page, you should see ‘javascript running’ logged to the console.

Now let’s add a React component to the page.

First, shut down the server and install React;

npm install --save-dev react react-dom

Now edit web/static/js/app.js again, and change the section we just added to look like this;

var HelloReact = React.createClass({
  render() {
    return(
      <h1>Hello from React</h1>
    )
  }
})

export var App = {
  run: function(){
    var element = document.getElementById("react-target")
    ReactDOM.render(<HelloReact />, element)
  }
}

According to the documentation, this should just work. But in my case, and perhaps yours too, I get the following error in the console when I try to run the app;

29 Dec 11:01:36 - error: Compiling of web/static/js/app.js failed. SyntaxError: web/static/js/app.js:Unexpected token (29:6)
  27 |   render() {
  28 |     return(
> 29 |       <h1>Hello from React</h1>
     |       ^
  30 |     )
  31 |   }
  32 | })

So, the JSX code we added, for our React component, is not being transpiled correctly. This is nothing to do with Phoenix – the error is happening during the asset build phase. You can confirm this by running;

node_modules/.bin/brunch build

This should give you the same error (possibly with nicer syntax highlighting).

After a lot of messing around, the way I was able to fix this was as follows;

First, install the React preset for the Babel transpiler;

npm install --save-dev babel-preset-react

Next, add that to the babel section of the brunch build pipeline by editing brunch-config.js. Look for the babel section;

// Configure your plugins
plugins: {
  babel: {
    // Do not use ES6 compiler in vendor code
    ignore: [/web\/static\/vendor/]
  }
},

Edit it to look like this (I don’t know why we also need to add the es2015 preset, but this doesn’t work without it);

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

Now try the brunch build command again, and it should complete with no errors.

When you run your phoenix application, and reload the browser, you should see “Hello from React”. You might see a quick flash of “No react here” when the original content appears, and is then replaced by javascript.

It took me a while to figure this out, so I hope this helps someone else.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s