2015-11-05 104 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组件。

相关问题