Search code examples
javascriptruby-on-rails-4reactjscoffeescriptreact-rails

Mount/Render a React component manually using JS


I am trying to use the react-rails with the kaminari gem. below piece of code is responsible for creating the Admins page with pagination, paginate being a kaminari method:

#app/views/dashboard/admins/_admins.html.erb
<div id="admins_component">
  <%= react_component 'Admins', {data: admins} %>
</div>
<%= paginate admins, :remote => true %>

on firing request with remote=true, this whole stuff is repainted, the response being generate through the following code:

#app/views/dashboard/admins/index.js.erb
<% if @admins.present? %>
$("#admin_wrapper").html("<%= escape_javascript(render partial: 'admins', locals: { admins: @admins } ) %>");
React.render("Admins", "#admins_component"); //How to make this work???
<% end %>

After the ajax request, the response is correctly generated and the ReactComponent is also being created in the HTML of the page as follows:

<div data-react-class="Admins" data-react-props="{"data":[{"id":26,"email":"[email protected]","created_at":"2016-03-16T09:10:48.220Z","updated_at":"2016-03-16T09:10:48.220Z"}]}"></div>

But the problem is that the component is not rendered/mounted. I tried mounting the component manually through console, but I am not sure if I was doing it correctly or not.

Moreover, the react extension in chrome displays the previous state of the Admin component, after the request for next page is fired: enter image description here

Aim is to replace the html of the red-box below, on clicking the pagination link:enter image description here

When I run Admin.prototype in console before/after clicking on the pagination link, I get the following output: enter image description here


Solution

  • react-rails includes some helpers for mounting components based on data-react-class and data-react-props attributes. The gem uses these helpers for mounting components and you can call them yourself, too.

    You should remove this line:

    React.render("Admins", "#admins_component"); //How to make this work???
    

    And replace it with:

    // Find any divs with `data-react-class` and mount them 
    ReactRailsUJS.mountComponents()
    

    It's ok to call that function anytime. Even if a component is already mounted, it will re-render it but not mess anything up!

    You can see all of react-rails's helpers in the react_ujs* files here:

    https://github.com/reactjs/react-rails/tree/master/lib/assets/javascripts