Search code examples
ruby-on-railsreactjsreact-rails

React Component rendering to string for some reason


For some reason, parts of my React component are rendering to string.

I'm using Rails with the react-rails gem and the sprockets-coffee-react gem to use JSX with Coffeescript.

Here's the code

show.html.erb

<%= react_component 'ArticleForm', {action: articles_path, 
                                    authenticity_token: form_authenticity_token,
                                    collection_id: @collection.id,
                                    } %>

article_form.js.coffee.cjsx

window.ArticleForm = React.createClass
  getInitialState: ->
    metadata: {}
    url: ''

  handleChange: ->
    console.log('test')

  render: ->
    <form accept-charset="UTF-8" action={this.props.action} method="post">
      <AuthenticityTokenInput authenticity_token={this.props.authenticity_token} />
    </form>

authenticty_token_input.js.coffee.cjsx

window.AuthenticityTokenInput = React.createClass
  render: ->
    <div style={{margin: 0, padding: 0, padding: 'inline'}}>
      <input name="utf8" type="hidden" value="✓">
      <input name="authenticity_token" type="hidden" value={this.props.authenticity_token}>
    </div>

And the output:

<input name="utf8" type="hidden" value="✓"> <input name="authenticity_token" type="hidden" value=zlZevmHku5ZU+UA998KwmJHAMn94uVkilrBj1iC/A8o=>

For some reason it renders the two inputs as plain text instead of actual html tags.

When I inspect element, here's what I get:

<form action="/articles" method="post" data-reactid=".0">
    <div style="margin:0;padding:inline;" data-reactid=".0.0">
        <span data-reactid=".0.0.0">&lt;input name="utf8" type="hidden" value="✓"&gt;
&lt;input name="authenticity_token" type="hidden" value=</span>
        <span data-reactid=".0.0.1">zlZevmHku5ZU+UA998KwmJHAMn94uVkilrBj1iC/A8o=</span>
        <span data-reactid=".0.0.2">&gt;</span>
    </div>
</form>

Solution

  • If you encounter tags being output as plain text when using CJSX, usually the cause is that one of the inner tags is malformed.

    In your case it's the <input> tags, which should be self closing. In CJSX (and JSX) you must provide either a closing tag, or make the tag self closing, eg. <input />

    The corrected authenticty_token_input.js.coffee.cjsx would look like this:

    window.AuthenticityTokenInput = React.createClass
      render: ->
        <div style={{margin: 0, padding: 0, padding: 'inline'}}>
          <input name="utf8" type="hidden" value="✓" />
          <input name="authenticity_token" type="hidden" value={this.props.authenticity_token} />
        </div>