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細節到歷史存儲。

從開發庫中的更好的錯誤消息是你所需要的未來的事情。