0

React_on_rails v9 makes passing props from server side a breeze, therefore making server side rendering so simple when prerender is set to true. But the challange one faces is when trying to implements React Router v4. The isssue with react router is inability to pass props from server side

I believe the documentation on upgrading from v7 to v9 will clear this issue -https://github.com/shakacode/react_on_rails/issues/809#issuecomment-334344969. But while I am waiting on that, I think we can still do something to profer solution to the routing issue.

Below are some steps to reproduce:

app/javascript/bundles/RailsNg/components/ServerHome.jsx

import React from 'react';
import ReactDOMServer from 'react-dom/server'
import { StaticRouter } from 'react-router';
import routes from './routes/routes';

const RailsNgOne = (props, railsContext) => {
const { location } = railsContext;

const context = {};

return (
  <StaticRouter
    location={location}
    context={context}
  >
   {routes}
  </StaticRouter>
  );
};

global.React = React
global.ReactDOMServer = ReactDOMServer

export default RailsNgOne

app/javascript/bundles/RailsNg/components/ClientHome.jsx

import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import routes from './routes/routes';

export default (props, railsContext) => {
  return (
    <Router>
      {routes}
    </Router>
  );

};

app/javascript/bundles/RailsNg/components/routes/routes.jsx

import React from 'react';
import { Route, Switch } from 'react-router';
import RailsNg from '../RailsNg';

export default (
  <Switch>
    <Route exact path="/" component={RailsNg} />
  </Switch>
);

app/javascript/bundles/RailsNg/components/RailsNg.jsx

import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Footer from './Footer'
import RailsNgHeader from './RailsNgHeader';

export default class RailsNg extends React.Component {
  render(){
    return(
      <div className="landing-container">
        <div className="landing-dashboard">
          <RailsNgHeader logo={this.props.logo} />
          <div className="dashboard-container">
            <div className="dashboard-title">
              <h2>Rails</h2><h1>NG</h1>
            </div>
            <div className="rails-logo">
              <img src={this.props.railslogo} alt="railslogo" className="rails-logo" />
            </div>
            <div className="dashboard-text">
              <p>An Acive Ruby on Rails Forum.</p>
              <p>this Landing page is SSR</p>
            </div>
            <div className="dashboard-button-container">
              <a href="#">
                <div className="dashboard-button">
                  <p>GET STARTED</p>
                </div>
              </a>
            </div>
          </div>
        </div>
        <div className="dashboard-advert">
          <image src={this.props.advert} alt="advert" className="dashboard-advert"/>
        </div>
        <Footer instagram={this.props.instagram} twitter=
{this.props.twitter} medium={this.props.medium} />
      </div>
    )
  }
}

app/javascript/packs/rails-ng-bundles.js

import ReactOnRails from 'react-on-rails';

import RailsNgOne from '../bundles/RailsNg/components/ClientHome';

ReactOnRails.register({
  RailsNgOne
})

app/javascript/packs/clientRegistration.js

import ReactOnRails from 'react-on-rails';

import RailsNgOne from '../bundles/RailsNg/components/ClientHome';

ReactOnRails.register({
  RailsNgOne
})

app/views/rails_ng/index.html.erb

<%= react_component("RailsNgOne", props: @images, prerender: true, raise_on_prerender_error: true, trace: true) %>

app/views/layouts/rails_ng.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>RailsNg</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': true %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': true %>
    <%= javascript_pack_tag 'rails-ng-bundle'%>

  </head>
  <body>
    <div class="landing-Header">
      <div class="header-button-container">
        <div class="landing-button.login">
          <%= link_to "Log Out", destroy_user_session_path, method: :delete %>
        </div>
      </div>
    </div>
    <%= yield %>

  </body>
</html>

app/controllers/rails_ng_controller.rb

# frozen_string_literal: true

class RailsNgController < ApplicationController
  # before_action :authenticate_user!

  layout "rails_ng"

  def index
    @images = {
      instagram: path_to_asset('landing/server-instagram'),
      twitter: path_to_asset('landing/server-twitter'),
      medium: path_to_asset('landing/server-medium'),
      logo: path_to_asset('landing/iquest-logo.png'),
      advert: path_to_asset('landing/RailsNigeria.png'),
      railslogo: path_to_asset('landing/rails-small.png')
   }
 end

 private

 def path_to_asset(asset)
   ApplicationController.helpers.asset_path(asset)
 end
end

config/application.rb - this file is configured to make rails to pick up saas fonts from assets pipeline.

require_relative 'boot'

require 'rails/all'

Bundler.require(*Rails.groups)

module Chatty
  class Application < Rails::Application

    config.load_defaults 5.1

    config.assets.paths << Rails.root.join("app", "assets", "fonts")

    if Rails.configuration.respond_to?(:sass)
      Rails.configuration.sass.tap do |config|
        config.preferred_syntax = :sass
      end
    end
  end
end

My results in Google Chrome console:

[SERVER] RENDERED RailsNgOne to dom node with id: RailsNgOne-react-component-8a9e89f0-3a29-4e82-9def-ed0dd15b091d with railsContext: {"inMailer":false,"i18nLocale":"en","i18nDefaultLocale":"en","href":"http://localhost:3000/","location":"/","scheme":"http","host":"localhost","port":3000,"pathname":"/","search":null,"httpAcceptLanguage":"en-US,en;q=0.8","serverSide":true}
createReactElement.js?46c3:40 RENDERED RailsNgOne to dom node with id: RailsNgOne-react-component-8a9e89f0-3a29-4e82-9def-ed0dd15b091d with props, railsContext: Objectadvert: "/assets/landing/RailsNigeria-19e84826196ea914bb17b5ba0d19b1a433147f64930a2d56eee88966b6fd6932.png"instagram: "/assets/landing/server-instagram-8309aeb4b134643b3849b1de08841274b887d7151c5696335cd8b22df607a4f9.png"logo: "/assets/landing/iquest-logo-8933b1ebd899e105fab35298969a54ded275285b751dc56f0314e5fe39945edd.png"medium: "/assets/landing/server-medium-7f29c9056261f92fb263996e317bd5a923a97d3867663c2f09c838e8cef2eda6.png"railslogo: "/assets/landing/rails-small-8a536281b93bba16489868c3387a2855c422e7e9f0b74e8bc09f89ea8c93738b.png"twitter: "/assets/landing/server-twitter-3f8241068c8426a8e17df940a1fd6706dacf7eca06623f5e0f440c0879a2c4d7.png"__proto__: Object Objecthost: "localhost"href: "http://localhost:3000/"httpAcceptLanguage: "en-US,en;q=0.8"i18nDefaultLocale: "en"i18nLocale: "en"inMailer: falselocation: "/"pathname: "/"port: 3000scheme: "http"search: nullserverSide: false__proto__: Object

The isssue with react router is inability to pass props from server side. This with-react-router-screenshot show that image props from server could not be passed. This was was due to RailsNg component passed through the router. I don't have enough reputation to post more than two links. But without RailsNg component passed through react router, image props render from server side.

Your help is highly appreciated. Thanks.

  • Nice writeup. However you don't explain the problem. I'd suggest creating a simple test reproduction repo on github and making screen shots that clearly show the problem. – justingordon Oct 13 '17 at 18:54
  • @justingordon thanks for coming.The problem is when passed **RailsNg** component through react router the image props from server side disappear, but on the browser console it indicates the presence of the props. when not using react router, image props are on the frontend. Here is the repo: [link](https://github.com/Ifegwu/chatty.git) – Daniel Agbanyim Oct 14 '17 at 14:04
  • > The isssue with react router is inability to pass props from server side. This with-react-router-screenshot show that image props from server could not be passed ==> Not true, as we do this on https://github.com/shakacode/react-webpack-rails-tutorial – justingordon Oct 14 '17 at 22:31
  • @justingordon, I think configuring asset path to pass props has to be done differently inside rails_ng_controller.rb. [link](https://github.com/Ifegwu/chatty.git). If it's true, kindly assist me. – Daniel Agbanyim Oct 15 '17 at 01:52

0 Answers0