1

我正在尝试在服务器上呈现反应应用程序,但似乎 renderToString 函数不会仅呈现路由 html 的页眉和页脚。通过查看页面代码,您只能看到服务器从 App.js 返回的页眉和页脚。但是路线中的代码不在页面上。

我正在使用 React-Router v4。我的代码如下所示:

服务器.js

import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import {StaticRouter} from 'react-router-dom';
import createMemoryHistory from 'history/createMemoryHistory';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { ConnectedRouter, routerMiddleware } from 'react-router-redux';
import { multiClientMiddleware } from 'redux-axios-middleware';
import ReactDOMServer from 'react-dom/server';
import api from "../src/actions/api";
import rootReducer from "../src/reducers/index";
import routes from '../src/routes/routes';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import Helmet from "react-helmet";
import render from './render';

const app = express();

global.navigator = { userAgent: 'all' };
app.use(express.static('assets'));

app.get('*', (req,res)=>{
const helmet = Helmet.renderStatic();
const axiosMiddlewareOptions = {};
const history = createMemoryHistory();
const appRouterMiddleware = routerMiddleware(history);
const createStoreWithMiddleware = applyMiddleware(multiClientMiddleware(api, axiosMiddlewareOptions), appRouterMiddleware)(createStore);
const store = createStoreWithMiddleware(rootReducer);

const context = {};

const appWithRouter = (
    <Provider store={store}>
        <MuiThemeProvider muiTheme={getMuiTheme()}>
            <StaticRouter location={req.url} context={context}>
                <ConnectedRouter history={history} children={routes}/>
            </StaticRouter>
        </MuiThemeProvider>
    </Provider>
);

if (context.url) {
    res.redirect(context.url);
    return
}

const html = ReactDOMServer.renderToString(appWithRouter);

res.status(200).send(render(html, helmet))
});

app.listen(8080, ()=>{
    console.log('Server is Listening')
});

渲染.js

export default (html, helmet) => `
    <!DOCTYPE html>
    <html ${helmet.htmlAttributes.toString()}>
        <head>
            <meta charset="UTF-8">
            ${helmet.title.toString()}
            <base href="/"/>
            <link href="./img/favikin-hw.png" rel="shortcut icon" type="image/x-icon" />
            <link href="./build/stylesheet.css" rel="stylesheet">
            <meta name="viewport" content=" width=device-width, maximum-scale=1">
        </head>

        <body>
            <div class="wrapper">${html}</div>
            <script type="text/javascript" src="./build/app.js"></script>
        </body>
    </html>

`;

应用程序.js

import React, { Component, PropTypes } from "react";
import Header from '../components/Header/Header';
import Footer from '../components/Footer/Footer';


class App extends Component {
  render() {
    return (
        <div className="wrapper-box">
            <div className="inner-wrapper">
                <Header/>
                {this.props.children}
            </div>
            <Footer/>
        </div>
    );
   }
  }

 App.propTypes = {
    children: PropTypes.object.isRequired
 };

 export default App;

roures.js

import React from 'react';
import App from '../containers/App';
import {
   Route,
   Switch
} from 'react-router-dom';
import MainPage from '../containers/MainPage/MainPage';
import DetailPage from '../components/DetailPage/DetailPage';
import AboutProject from '../containers/AboutProject/AboutProject';
import Contacts from '../containers/Contacts/Contacts';
import SectionPage from '../containers/SectionPage/SectionPage';
import SearchPage from '../containers/SearchPage/SearchPage';
import NoMatch from '../containers/NoMatch/NoMatch';


export default (
<App>
<div>
    <Switch>
        <Route exact={true} path='/' component={MainPage} />
        <Route path='/about_the_project' component={AboutProject} />
        <Route path='/contacts' component={Contacts} />
        <Route path="/search-results/:category/:term" component={SearchPage}/>
        <Route exact={true} path='/:name' component={SectionPage} />
        <Route path="/articles/:slug" component={DetailPage}/>
        <Route path="/events/:slug" component={DetailPage}/>
        <Route path="/news/:slug" component={DetailPage}/>
        <Route path="/interviews/:slug" component={DetailPage}/>
        <Route path="/technologies/:slug" component={DetailPage}/>
        <Route path='*' component={NoMatch}/>
    </Switch>
</div>
</App>
)

客户端.js

import React from 'react';
import { render } from 'react-dom';
import createBrowserHistory from 'history/createBrowserHistory';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { ConnectedRouter, routerMiddleware } from 'react-router-redux';
import { multiClientMiddleware } from 'redux-axios-middleware';
import api from "./actions/api";
import rootReducer from "./reducers/index";
import routes from './routes/routes';
import { BrowserRouter } from 'react-router-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import '../assets/css/bootstrap.min.css';
import '../assets/style.css';
import '../node_modules/react-datetime/css/react-datetime.css';
import '../node_modules/react-select/dist/react-select.min.css';

const axiosMiddlewareOptions = {};

const history = createBrowserHistory();
const appRouterMiddleware = routerMiddleware(history);
const createStoreWithMiddleware = applyMiddleware(multiClientMiddleware(api, axiosMiddlewareOptions), appRouterMiddleware)(createStore);
const store = createStoreWithMiddleware(rootReducer, {}, window.devToolsExtension ? window.devToolsExtension() : f => f);

render(
<Provider store={store}>
    <MuiThemeProvider>
        <ConnectedRouter history={history} children={routes}/>
    </MuiThemeProvider>
</Provider>,
document.querySelector('.wrapper'));
4

0 回答 0