react + SSR:TypeError:match不是函数

时间:2017-11-27 17:07:40

标签: javascript node.js reactjs

我正在关注本教程 - https://www.youtube.com/watch?v=Smk2FusU_70(正好在28:38标记处)

然而它在v4之前出现了,我收到了一个错误:

/Users/morganallen/Desktop/react_ssr/myapp/server/index.js:55
            match({routes, location: req.url}, (error, redirect, ssrData) => {
            ^

TypeError: match is not a function
    at fs.readFile (/Users/morganallen/Desktop/react_ssr/myapp/server/index.js:55:13)
    at tryToString (fs.js:455:3)
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:442:12)

我在这个答案中看到他看起来有类似的问题 - What's wrong with this ReactRouter.match() implementation?

虽然我不太确定else{} match({})语句中的更改require('import-export') require('babel-core/register')({presets: ['es2015', 'react']}) const http = require('http') const path = require('path') const fs = require('fs') const express = require('express') const react = require('react') const reactRouter = require('react-router') const reactDomServer = require('react-dom/server') const renderToString = reactDomServer.renderToString const match = reactRouter.match const RouterContext = reactRouter.RouterContext const staticFiles = [ '/static/*', '/logo.svg', '/asset-manifest.json', '/favicon.ico' ] const app = express() app.server = http.createServer(app) app.use(express.static('../build')) staticFiles.forEach(file => { app.get(file, (req, res) => { const filePath = path.join(__dirname, '../build', req.url) res.sendFile(filePath) }) }) const routes = require('../src/routes').default() app.get('*', (req, res) => { const error = () => res.status(404).send('404') const htmlFilePath = path.join(__dirname, '../build', 'index.html') fs.readFile(htmlFilePath, 'utf8', (err, htmlData) => { if(err) { error() } else{ match({routes, location: req.url}, (error, redirect, ssrData) => { if(error){ error() } else if(redirect){ res.redirect(302, redirect.pathname + redirect.search) } else if(ssrData){ const ReactApp = renderToString(react.createElement(RouterContext, srrData) ) const RenderApp = htmlData.replace('{{SSR}}', ReactApp) res.status(200).send(RenderApp) } else{ error() } }) } }) }) app.server.listen( process.env.PORT || 8080) console.log(app.server.address().port)

我该怎么做才能让它发挥作用?

{
  "name": "myapp",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "babel-core": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "import-export": "^1.0.1",
    "react": "^16.1.1",
    "react-dom": "^16.1.1",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "react-scripts": "1.0.17"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

我的package.json文件

def extract_rows(dfl, starts, L, fillval=np.nan):
    a = dfl.values

    idx = np.asarray(starts)[:,None] + range(L)
    valid_mask = idx < dfl.shape[1]
    idx[~valid_mask] = 0

    val = a[np.arange(len(idx))[:,None],idx]
    return pd.DataFrame(np.where(valid_mask, val, fillval))

1 个答案:

答案 0 :(得分:1)

使用matchPath用于React Router 4 +

如上所述,虽然您的问题不在主题......您应该使用StaticRouter用于React Router 4

app.get("*", ( request, response ) => {
const store = configureStore();

const promises = routes.reduce((acc, route) => {
    if (matchPath(request.url, route) && route.component && route.component.initialAction) {
        acc.push(Promise.resolve(store.dispatch(route.component.initialAction())));
    }
    return acc;
}, []);

Promise.all(promises)
    .then( () => {
        const context={};
        const markup = renderToString(
          <Provider store={store}>
              <StaticRouter location={request.url} context={context}>
                  <App />
              </StaticRouter>
          </Provider>
        );

        const initialData = {};

        response.send(`
            <!DOCTYPE html>
            <html class="no-js" lang="en">
                <head>
                </head>
                <body>  
                    <div id="root">${markup}</div>
                    <script src="/app.bundle.js" defer></script>
                    <script>window.__initialData__ = ${serialize(initialData)}</script>
                </body>
            </html>`);

    });
});

我使用它来调用我可能想要为服务器端的组件预加载数据的任何组件上的initialAction方法(它是静态的)。但是,如果没有这种方法,您可以编写所有组件,下面的代码也可以正常工作。

请注意,路线是另一个文件中的对象,例如

import Home from "./components/Home";

const routes = [
    {
        path: "/",
        exact: true,
        component: Home
    }
];

export default routes;