我正在尝试使用react-router 4进行服务器端渲染.我遵循此处提供的示例https://reacttraining.com/react-router/web/guides/server-rendering/putting-it-all-together
根据服务器上的示例我们应该使用StaticRouter.当我按照示例导入时,我看到StaticRouter是未定义的
import {StaticRouter} from 'react-router';
Run Code Online (Sandbox Code Playgroud)
在网上做了一些研究之后,我发现我可以使用react-router-dom.现在我的import语句看起来像这样.
import {StaticRouter} from 'react-router-dom';
Run Code Online (Sandbox Code Playgroud)
但是,当我运行代码时,我将Invariant Violation: Browser history needs a DOM进入浏览器.
我的server.js文件代码
....
app.get( '*', ( req, res ) => {
const html = fs.readFileSync(path.resolve(__dirname, '../index.html')).toString();
const context = {};
const markup = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context} >
<App/>
</StaticRouter>
);
if (context.url) {
res.writeHead(302, {
Location: context.url
})
res.end();
} else {
res.send(html.replace('$react', markup));
}
} );
....
Run Code Online (Sandbox Code Playgroud)
和我的client/index.js代码
....
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), root);
....
Run Code Online (Sandbox Code Playgroud)
更新v1 将我的示例减少到最小值并仍然得到相同的错误.
clientIndex.js
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'
import App from '../App'
ReactDOM.render((
<BrowserRouter>
<App/>
</BrowserRouter>
), document.getElementById('app'))
Run Code Online (Sandbox Code Playgroud)
serverIndex.js
import { createServer } from 'http'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { StaticRouter } from 'react-router'
import App from '../App'
createServer((req, res) => {
const context = {}
const html = ReactDOMServer.renderToString(
<StaticRouter
location={req.url}
context={context}
>
<App/>
</StaticRouter>
)
res.write(`
<!doctype html>
<div id="app">${html}</div>
`)
res.end()
}).listen(3000);
Run Code Online (Sandbox Code Playgroud)
App.js
import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import routes from "./client/routes";
const App = ( ) => (
<Router>
<Route path="/" exact render={( props ) => ( <div>Helloworld</div> )} />
</Router>
)
export default App;
Run Code Online (Sandbox Code Playgroud)
Roh*_*ran 12
您需要使用不同的历史记录提供程序进行服务器端呈现,因为您在服务器上没有真正的DOM(以及浏览器的历史记录).因此,使用路由器替换BrowserRouter并在app.js中使用备用历史记录提供程序可以解决此问题.此外,您不必使用两个包装器.您在app.js和clientIndex.js中使用BrowserRouter两次,这是不必要的.
import { Route, Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
const history = createMemoryHistory();
<Router history={history}>
<Route path="/" exact render={( props ) => ( <div>Helloworld</div> )} />
</Router>
Run Code Online (Sandbox Code Playgroud)
您现在可以使用ConnectedRouter替换StaticRouter,它可以在客户端和服务器中使用.我使用以下代码在历史记录中进行选择并将其导出以用于ConnectedRouter的历史记录.
export default (url = '/') => {
// Create a history depending on the environment
const history = isServer
? createMemoryHistory({
initialEntries: [url]
})
: createBrowserHistory();
}
Run Code Online (Sandbox Code Playgroud)
Koo*_*ndy 11
在 clientIndex.js 中
而不是 BrowserRouter 使用 StaticRouter。
从'react-router-dom'导入{ BrowserRouter};
从'react-router-dom'导入{StaticRouter}
正如评论中基本上指出的那样,可能是由于不小心将您的App组件包装<BrowserRouter>在中而导致出现此错误(如我所说),而应该包装您的客户端应用。
import React from 'react'
const App = () => <h1>Hello, World.</h1>
export default App
Run Code Online (Sandbox Code Playgroud)
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import ReactDOM from 'react-dom'
import App from './App'
const render = Component => {
ReactDOM.render(
<BrowserRouter>
<Component />
</BrowserRouter>,
document.getElementById('app')
)
}
render(App)
Run Code Online (Sandbox Code Playgroud)
另请参阅React Router文档。
| 归档时间: |
|
| 查看次数: |
19695 次 |
| 最近记录: |