3

我创建使用与反应护栏(V1.6.2)轨(v4.2.6)这个样本回购和反应路由器(V2.0.0-RC5): https://github.com/pioz/rails_with_react_and_react_router_example服务器使用Rails渲染+反应护栏宝石+反应路由器

在文件app/views/application/react_entry_point.html.erb我呈现组件MountUp

<%= react_component('MountUp', {}, {prerender: false}) %> 

组件MountUp使我的路由器:

class MountUp extends React.Component { 
    render() { 
    return(
     <Router history={History}> 
     <Route path="/" component={App}> 
      <IndexRoute component={Index} /> 
      <Route path="/contact" component={Contact}/> 
      <Route path="/about" component={About}/> 
     </Route> 
     </Router> 
    ) 
    } 
} 

所有工作正常,但如果我更改选项prerender: true我得到一个奇怪的错误React::ServerRendering::PrerenderError in Application#react_entry_point

Encountered error "Error: Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings." when prerendering MountUp with {} 
Object.invariant [as default] ((execjs):21983:16) 
createHashHistory ((execjs):24108:130) 
(execjs):22633:20 
wrapDeprecatedHistory ((execjs):25285:61) 
createRouterObjects ((execjs):25259:23) 
componentWillMount ((execjs):25228:38) 
ReactCompositeComponentMixin.mountComponent ((execjs):8138:13) 
wrapper [as mountComponent] ((execjs):3131:22) 
Object.ReactReconciler.mountComponent ((execjs):6583:36) 
ReactCompositeComponentMixin.mountComponent ((execjs):8153:35) 
/Users/pioz/.rvm/gems/ruby-2.3.0/gems/execjs-2.6.0/lib/execjs/external_runtime.rb:39:in `exec' 
... 

我怎样才能使这个应用程序的服务器端?这是正确的方法吗?

回答

1

找到了解决方法:我们需要两个版本的组件MountUp的:使用浏览器的历史记录和使用假记忆历史的服务器版本客户端版本。这两个版本的组件:

// client version 
class MountUp extends React.Component { 
    render() { 
    return(
     <Router history={History}> 
     <Route path="/" component={App}> 
      <IndexRoute component={Index} /> 
      <Route path="/contact" component={Contact}/> 
      <Route path="/about" component={About}/> 
     </Route> 
     </Router> 
    ) 
    } 
} 


// server version 
class MountUp extends React.Component { 
    render() { 
    return(
     <Router history={createMemoryHistory(this.props.path)}> 
     <Route path="/" component={App}> 
      <IndexRoute component={Index} /> 
      <Route path="/contact" component={Contact}/> 
      <Route path="/about" component={About}/> 
     </Route> 
     </Router> 
    ) 
    } 
} 

我们还需要创建一个URL路径等于请求的内存历史:要做到这一点,我们可以传递给组件的新道具path用的路径要求:

<%= react_component('MountUp', {path: request.path}, {prerender: true}) %> 
+0

在服务器端的情况下,当页面在客户端上呈现的仍然使用memoryHistory正因为如此,如果我们点击某个链接的网址不会改变,但内容会改变。有没有办法避开它? –

+1

您需要使用2个不同的组件MountUp,一个用于客户端和一个服务器端...的application.js包括mountup_client.jsËserver.js包括mountup_server.js – Pioz

1

我想告诉它不预渲染不会帮助

prerender: false 

另外,不要因为它表明,抓住开发版本,所以它会告诉你多一点

use the non-minified dev environment for the full error message 

你告诉它建立基于History对象的路由,该对象应该表示用户已经请求的地址(url)。在服务器端,您需要以某种方式构建一个对象,该对象将用一个条目模拟浏览器历史记录:请求的url。

我已经在节点中使用终极版使用该这样做:

import createHistory from 'history/lib/createMemoryHistory'; 


var reducer = combineReducers(reducers); 

const store = compose(
    applyMiddleware(promiseMiddleware, thunk), 
    reduxReactRouter({routes, createHistory}) 
)(createStore)(reducer, {}); 

但是,你将需要采取不同的方法,以获得Rails的request细节到历史存储。

从开发库中的更好的错误消息是你所需要的未来的事情。