React_on_rails v9 使从服务器端传递道具变得轻而易举,因此当
prerender
设置为 true 时,使服务器端渲染变得如此简单。但面临的挑战是在尝试实现 React Router v4 时。反应路由器的问题是无法从服务器端传递道具
我相信有关从 v7 升级到 v9 的文档将解决此问题 - https://github.com/shakacode/react_on_rails/issues/809#issuecomment-334344969。但在我等待的同时,我认为我们仍然可以做一些事情来解决路由问题。
以下是一些重现的步骤:
应用程序/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
应用程序/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>
);
};
应用程序/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>
);
应用程序/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>
)
}
}
应用程序/javascript/packs/rails-ng-bundles.js
import ReactOnRails from 'react-on-rails';
import RailsNgOne from '../bundles/RailsNg/components/ClientHome';
ReactOnRails.register({
RailsNgOne
})
应用程序/javascript/packs/clientRegistration.js
import ReactOnRails from 'react-on-rails';
import RailsNgOne from '../bundles/RailsNg/components/ClientHome';
ReactOnRails.register({
RailsNgOne
})
应用程序/视图/rails_ng/index.html.erb
<%= react_component("RailsNgOne", props: @images, prerender: true, raise_on_prerender_error: true, trace: true) %>
应用程序/视图/布局/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>
应用程序/控制器/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 - 这个文件被配置为让 rails 从资产管道中获取 saas 字体。
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
我在 Google Chrome 控制台中的结果:
[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
反应路由器的问题是无法从服务器端传递道具。这个with-react-router-screenshot显示无法传递来自服务器的图像道具。这是由于RailsNg组件通过了路由器。我没有足够的声誉发布两个以上的链接。但是没有RailsNg组件通过反应路由器,图像道具从服务器端渲染。
非常感谢您的帮助。谢谢。