2015-11-05 109 views
2

我正在處理最近的反應。我正在使用服務器渲染和react-router,但它只能渲染反應組件中的HTML,並且我需要通過中的ajax獲取初始數據。我可以使用React中的數據進行服務器渲染嗎?

問題在於某些頁面/組件,他們需要初始數據來呈現。因此,如果用戶直接訪問這樣的頁面(通過輸入url或刷新),頁面會中斷,因爲服務器無法在沒有初始數據的情況下渲染它。

我想我可以從數據庫中獲取數據並在服務器中呈現時將其插入到模板中?就像經典的前端模板或PHP所做的一樣。

如果沒辦法,渲染首頁數據的最佳做法是什麼?

現在我的服務器代碼是這樣的:

router.get('*', function(req, res) { 
    console.log('GET ADMIN'); 
    match({ 
    routes: appRoutes, 
    location: req.originalUrl 
    }, (error, redirectLocation, renderProps) => { 
    if (error) { 
     res.status(500) 
     .send(error.message); 
    } else if (redirectLocation) { 
     res.status(302) 
     .redirect(redirectLocation.pathname + redirectLocation.search); 
    } else if (renderProps) { 
     var content = renderToString(<RoutingContext {...renderProps}/>); 
     var html = swig.renderFile('src/client/admin.html', { 
     content: content 
     }); 
     res.status(200) 
     .send(html); 
    } else { 
     res.status(404) 
     .send('Not found'); 
    } 
    }); 
}); 
+0

它被稱爲同構或通用渲染,我做了一個簡單的例子沒有通量在這裏 - https://github.com/DominicTobias/universal-react/。我建議你谷歌,因爲有很多不同的方法。這不是最簡單的主題。 –

+0

@DominicTobias Thx。我已閱讀關於同構應用程序的一些教程。我學到的是如何在沒有數據的情況下呈現HTML。你能檢查我剛剛編輯的帖子嗎?所以你的意思是我可以使用實時數據渲染頁面(從數據庫中獲取)?這是一個好消息。我現在要讀你的鏈接。 –

回答

1

最後,我發現在GitHub上的答案:https://github.com/rackt/react-router/issues/1969#issuecomment-140988110

這種方法插入你的服務器渲染時需要到HTML模板中的所有數據,並獲得前端的數據context。所有組件都可以通過context獲取數據。我使用<DataWrapper>組件來包裝原始根應用組件。在服務器端渲染時:

data = JSON.stringify(data); // data is an object 
ReactDOMServer.renderToString(<DataWrapper data={data}><RoutingContext {...renderProps}/></DataWrapper>) 

<DataWrapper>是這樣的:在客戶端

import React from 'react'; 

class DataWrapper extends React.Component { 

    getChildContext() { 

     return { 
      data: this.props.data 
     }; 
    } 

    render() { 

     return this.props.children; 
    } 
} 

DataWrapper.childContextTypes = { 
    data: React.PropTypes.object.isRequired 
}; 

export default DataWrapper; 

var data = JSON.parse(document.getElementById('data').innerHTML), 
    history = createBrowserHistory(); 

ReactDOM.render(<DataWrapper data={ data }><Router history={ history }>{ routes }</Router></DataWrapper>, document.getElementById('app')); 

獲得組件通過上下文中的數據:

class someComponent extends React.Component { 

    constructor (props, context) { 

     super(props, context); 
     this.state = context.data.someData; 
    } 
} 

someComponent.contextTypes = { 
    data: React.PropTypes.object.isRequired 
}; 

export default someComponent; 

它效果不錯

0

使用AJAX調用的初始化的問題是,它迫使你先渲染沒有數據,然後重新渲染,一旦數據到達。

更好的方法是將數據包含在頁面中,以便在初始渲染時使用它。例如

<script> 
    var __INITIAL_DATA__ = { /* etc */ } 
</script> 

是的全局變得很醜。但在這種情況下是必要的。你只用它來初始化你的React組件。 (或者你的商店,如果你使用的是Flux。)

是的,在同構/通用應用程序中,您可以在服務器端代碼中使用相同的數據。就像在PHP和其他服務器端語言一樣。只有你的服務器端代碼不會從全局變量中提取。數據應直接傳遞到您正在安裝的React組件。

相關問題