反应+ SSR:TypeError:匹配不是一个函数

我正在按照这个教程 – 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) 

我在这个答案中看到他看起来像是有一个类似的问题 – 这个ReactRouter.match()实现有什么问题?

虽然我不太确定match({})else{}语句中的更改

我该怎么做才能使它工作?

 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) 

我的package.json文件

 { "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" } } 

为反应路由器4 +使用matchPath

如上所述,虽然从你的问题脱离主题…你应该使用StaticRouter的反应路由器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;