0

I'm trying to figure out how to use react-rails with my Rails 5 gem.

At the moment, I'm trying to follow the tutorial in this post. https://medium.com/technically-speaking/isomorphic-reactjs-app-with-ruby-on-rails-part-1-server-side-rendering-8438bbb1ea1c#.iwd44r60v

I can't get the page to render at present. I use app_roles instead of posts, but otherwise I've followed the steps shown in the tutorial.

I have two files in my app/assets/javascripts/components folder.

app_role.js.jsx has:

var AppRole = React.createClass({
    render: function() {
        return (
            <div className="h2">
                <AppRoleHeader app_role={this.props.app_role} />
                <AppRoleContent app_role={this.props.app_role} />
            </div>
        );
    }
});
var AppRoleHeader = React.createClass({
    render: function() {
        return (
            <div className="label">
                <h2>{this.props.app_role.title}</h2>
                <div className="label">
                    By {this.props.app_role.title} – {this.props.app_role.created_at}
                </div>
            </div>
        );
    }
});

var AppRoleContent = React.createClass({
    render: function() {
        return (
            <div className="label">
                {this.props.app_role.display_name}
            </div>
        );
    }
});

app_roles_list.js.jsx has:

var AppRolesList = React.createClass({
    getInitialState: function() {
        return { posts: this.props.initialAppRoles };
    },

    render: function() {
        var posts = this.state.app_roles.map(function(app_role) {
            return <AppRole key={app_role.id} app_role={app_role} />;
        });

        return (
            <div className="label">
                {app_roles}
            </div>
        );
    }
});

When I try to render this in my app_roles/index.html.erb file with:

<%= react_component('AppRolesList',
                    { initialAppRoles: @app_roles },
                    { prerender: params[:noprerender].nil? }) %>

I get an error that says:

ExecJS::RuntimeError at /app_roles
/private/var/folders/75/70zm4s4j14q74tfqpjvh49s80000gp/T/execjs20161015-7497-1bhq2x0js:24066
        return <div className="h2">
               ^

SyntaxError: Unexpected token <
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)
    at startup (node.js:139:18)
    at node.js:974:3

I don't understand this error message. I've read some posts describing a problem where the return method has two elements being returned. I tried removing the div h2 tag altogether and putting the two returned elements in an array, but that didn't work either.

I have also read posts describing problems configuring babel. I don't follow the gist of those comments. In my config development.rb, I have:

config.react.variant = :development
  config.react.addons = true
  config.react.jsx_transform_options = {
    blacklist: ['spec.functionName', 'validation.react', 'strict'], # default options
    # optional: ["transformerName"],  # pass extra babel options
    whitelist: ["useStrict"] # even more options
  }

I'm not sure what I'm supposed to write in the optional: field. I assumed react-rails would give me some kind of default settings that would automatically work.

I also tried adding:

/** @jsx React.DOM */

to the top of each of the component files. Although that makes no difference to the problem.

I also tried adding this to config/application.rb

config.react.jsx_transformer_class = React::JSX::JSXTransformer

That doesn't change anything either.

I also tried adding this on my command line:

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

It made no difference to this problem.

Can anyone see what I need to do to get this page to load?

Application.js has:

//= require jquery
//= require jquery_ujs
//= require tether
//= require bootstrap-sprockets
//= require turbolinks
//= require react
//= require react_ujs
// require react_bootstrap
//= require components
//= require_tree .
6
  • 1
    I don't know what kind of pre-setup project stub you are using but that error can mean only one thing: babel is not setup properly. Commented Oct 15, 2016 at 0:32
  • Ok - I don't know what "pre-setup project stub" means. I am using react-rails. I followed the setup instructions for that gem. Do you know where to find babel config instructions for react-rails? I have node installed. I didn't know I had to search for separate instructions to finish configuring an app to work with rails. Commented Oct 15, 2016 at 0:36
  • It is supposed to make your life easier by setting things up correctly and putting configurations in place you had to do by yourself, but apperantly it's not so helpful. You won't find many people here that has experience with a "react-rails" gem so good luck. Commented Oct 15, 2016 at 1:00
  • Do you know of a product that configures a rails app to work with react-rails? I don't mind starting a new app to get this working. Commented Oct 15, 2016 at 1:11
  • Can you also add application.js code? I followed this tutorial and was able to set up. Commented Oct 15, 2016 at 6:13

1 Answer 1

1

Couple of things to fix:

var AppRolesList = React.createClass({
    getInitialState: function() {
        return { posts: this.props.initialAppRoles };
    },

    render: function() {
        var posts = this.state.app_roles.map(function(app_role) {
            return <AppRole key={app_role.id} app_role={app_role} />;
        });

        return (
            <div className="label">
                {app_roles}
            </div>
        );
    }
});

You are copying the initialAppRoles prop into the posts state variable (which is mostly an anti-pattern), but then you expect this.state.app_roles which is never set.

You should just delete the whole getInitialState function here and directly use:

var posts = this.props.initialAppRoles.map(function(app_role) {
  return <AppRole key={app_role.id} app_role={app_role} />;
});

Second bug to fix: you are creating an array of posts in the render function, but then you have app_roles in your return which is not set. Correct that to have:

return (
  <div className="label">
    {posts}
  </div>
);

I copied pasted your code into my Rails setup (which uses react-rails) and it worked with prerendering on and off.

On a side note, I strongly recommend having one component per .js.jsx file with the underscore cased name of the component as its name. It'll make things easier to find in the future.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.