迁移到 React-router v4 后,我注意到我必须找到一种方法来将请求的 URL 与应用程序路由文件(即 JSX)进行比较。
文件routes.js
包含所有react-router
路由并相应导出。因此,我想知道如何获取定义的路径,以与服务器端请求的 URL 进行比较或匹配;如果不匹配,这将返回 404 或任何其他 React 组件!
找到下面的源代码:
// routes.js
import React from 'react'
import { Route } from 'react-router'
import example from './example'
export default (
<Route path='/' component={example.containers.App} />
)
这是 Express 获取请求处理程序:
app.get('*', (req, res) => {
const preloadedState = {'foobar': 1}
// Create a new Redux store instance
const store = configureStore(preloadedState)
// Render the component to a string
const myAppHtml = renderToString(<StaticRouter context={{}} location={req.url}>
<Provider store={store}>
<MyApp store={store} />
</Provider>
</StaticRouter>)
// Grab the initial state from our Redux store
const finalState = store.getState()
res.render('index', {
app: myAppHtml,
state: JSON.stringify(finalState).replace(/</g, '\\x3c'),
bundle: webpackAssets.main.js,
build: config.build_name,
css: '/assets/css/main.min.css'
})
})
您还可以在下面找到完整的服务器代码:
// server.dev.js
import express from 'express'
import path from 'path'
import superagent from 'superagent'
import chalk from 'chalk'
import React from 'react'
import { renderToString } from 'react-dom/server'
import { StaticRouter, matchPath } from 'react-router'
import routes from './src/js/routes'
import configureStore from './src/js/rootStore'
import { Provider } from 'react-redux'
import MyApp from './src/js/example/containers/app'
const app = express()
const port = process.env.PORT ? process.env.PORT : 3000
var serverInstance = null
var dist = path.join(__dirname, (['staging', 'production'].indexOf(process.env.NODE_ENV) > -1 ? 'dist/' + process.env.NODE_ENV : 'src'))
var config = null
const webpack = require('webpack')
const webpackHotMiddleware = require('webpack-hot-middleware')
const webpackDevConfig = require('./webpack.dev.config')
const compiler = webpack(require('./webpack.dev.config'))
var webpackDevMiddleware = require('webpack-dev-middleware')
const webpackAssets = require('./webpack-assets.json')
config = require('./config')
/**
* Process error handling
*/
process.on('uncaughtException', (err) => {
throw err
})
process.on('SIGINT', () => {
serverInstance.close()
process.exit(0)
})
app.set('views', path.join(__dirname, 'src'))
app.set('view engine', 'ejs')
app.use(webpackDevMiddleware(compiler, {
noInfo: true,
publicPath: webpackDevConfig.output.publicPath,
stats: {
colors: true,
hash: false,
version: true,
timings: false,
assets: false,
chunks: false,
modules: false,
reasons: false,
children: false,
source: false,
errors: true,
errorDetails: true,
warnings: true,
publicPath: false
}
}))
app.use(webpackHotMiddleware(compiler, {
log: console.log
}))
/**
* The Cross origin resource sharing rules
*/
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE')
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type')
res.setHeader('Access-Control-Allow-Credentials', true)
next()
})
/**
* Health check
*/
app.use('/healthcheck', (req, res) => {
res.json({
'env': {
'NODE_ENV': process.env.NODE_ENV
}
})
res.end()
})
app.use('/api/test', (req, res) => {
superagent
.get('https://jsonip.com/')
.end((err, response) => {
if (err) {
console.log('api test err', err)
}
res.send(response.body)
})
})
app.use('/assets', express.static(dist))
// READ HERE
app.get('*', (req, res) => {
const preloadedState = {'foobar': 1}
// Create a new Redux store instance
const store = configureStore(preloadedState)
// Render the component to a string
const myAppHtml = renderToString(<StaticRouter context={{}} location={req.url}>
<Provider store={store}>
<MyApp store={store} />
</Provider>
</StaticRouter>)
// Grab the initial state from our Redux store
const finalState = store.getState()
res.render('index', {
app: myAppHtml,
state: JSON.stringify(finalState).replace(/</g, '\\x3c'),
bundle: webpackAssets.main.js,
build: config.build_name,
css: '/assets/css/main.min.css'
})
})
serverInstance = app.listen(port, (error) => {
if (error) {
console.log(error) // eslint-disable-line no-console
}
console.log(chalk.green('[' + config.build_name + '] listening on port ' + port + '!'))
})
一个解决方案是声明一个包含所有路由的变量,但这会违反 DRY 原则;或者也许,转译 paths.js 并获得非 JSX 版本,但到目前为止我的所有想法听起来都有些过分了!
最佳答案
我认为"matchPath" (从react-router-dom导出)就是你正在寻找的。
关于javascript - 服务器端的 React-router v4,如何将请求 url 与 jsx 路由匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44074541/