【问题标题】:React Router - Browser History needs a domReact Router - 浏览器历史需要一个 dom
【发布时间】:2018-12-26 23:04:00
【问题描述】:

我正在为我的应用程序使用 React.js 和 express。我正在尝试为应用程序设置 react-router-dom。

但是,当我尝试运行应用程序时,我收到了警告:

Invariant Violation: Browser history needs a DOM
    at invariant (/home/jshen/playlistTracker/node_modules/invariant/invariant.js:40:15)
    at createBrowserHistory (/home/jshen/playlistTracker/node_modules/history/createBrowserHistory.js:49:27)
    at new BrowserRouter (/home/jshen/playlistTracker/node_modules/react-router-dom/BrowserRouter.js:46:197)
    at processChild (/home/jshen/playlistTracker/node_modules/react-dom/cjs/react-dom-server.node.development.js:2095:14)
    at resolve (/home/jshen/playlistTracker/node_modules/react-dom/cjs/react-dom-server.node.development.js:2061:5)
    at ReactDOMServerRenderer.render (/home/jshen/playlistTracker/node_modules/react-dom/cjs/react-dom-server.node.development.js:2380:22)
    at ReactDOMServerRenderer.read (/home/jshen/playlistTracker/node_modules/react-dom/cjs/react-dom-server.node.development.js:2354:19)
    at renderToString (/home/jshen/playlistTracker/node_modules/react-dom/cjs/react-dom-server.node.development.js:2726:25)
    at handleRender (/home/jshen/playlistTracker/dist/server.js:755:41)
    at Layer.handle [as handle_request] (/home/jshen/playlistTracker/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/home/jshen/playlistTracker/node_modules/express/lib/router/index.js:317:13)
    at /home/jshen/playlistTracker/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/home/jshen/playlistTracker/node_modules/express/lib/router/index.js:335:12)
    at next (/home/jshen/playlistTracker/node_modules/express/lib/router/index.js:275:10)
    at expressInit (/home/jshen/playlistTracker/node_modules/express/lib/middleware/init.js:40:5)
    at Layer.handle [as handle_request] (/home/jshen/playlistTracker/node_modules/express/lib/router/layer.js:95:5)

App.jsx

import React, {Component, Fragment} from 'react';
import {BrowserRouter, Switch, Route } from 'react-router-dom'
import { NavBar } from './layouts'
import Main from './main'


class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      currentUser: {name: "testUser"},
      favourite: [],
      playlist: []
    };
  }

  render() {
    return (
      <BrowserRouter>
        <NavBar>
          <Switch>
            <Route exact path ="/" render={
              () => <div> hello </div>
            }/>
          </Switch>
        </NavBar>
      </BrowserRouter>
    )
  }

}

export default App;

server.js

import express from 'express';
import React from 'react';
import App from '../client/App.jsx';

import { renderToString } from 'react-dom/server'
import { SheetsRegistry } from 'react-jss/lib/jss'
import JssProvider from 'react-jss/lib/JssProvider'
import {
  MuiThemeProvider,
  createMuiTheme,
  createGenerateClassName,
} from '@material-ui/core/styles'

const app = express();
const port = 3000;

// This is fired every time the server side receives a request.
app.use(handleRender);
app.listen(port);

// inject our initial component HTML and CSS into a template to be rendered on the client side.
function renderFullPage(html, css) {
  return `
    <!doctype html>
    <html>
      <head>
        <title>Material-UI</title>
      </head>
      <body>
        <div id="root">${html}</div>
        <style id="jss-server-side">${css}</style>
      </body>
    </html>
  `;
}

// When rendering, we will wrap App, our root component, inside a JssProvider and MuiThemeProvider 
// to make the sheetsRegistry and the theme available to all components in the component tree.
// Render the initial HTML of our component before we send it to the client side. 
// To do this, we use ReactDOMServer.renderToString().
function handleRender(req, res) {
  // Create a sheetsRegistry instance.
  const sheetsRegistry = new SheetsRegistry();

  // Create a theme instance.
  const theme = createMuiTheme({
    palette: {
      primary: {
        light: '#757575',
        main: '#a4a4a4',
        dark: '#494949',
        contrastText: '#ffffff',
      },
      secondary: {
        light: '#263238',
        main: '#a4a4a4',
        dark: '#494949',
        contrastText: '#ffffff',
      },
      // accent: red,
      // type: 'light',
    },
  });

  const generateClassName = createGenerateClassName();

  // Render the component to a string.
  const html = renderToString(
    <JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
      <MuiThemeProvider theme={theme} sheetsManager={new Map()}>
        <App />
      </MuiThemeProvider>
    </JssProvider>
  )

  // Grab the CSS from our sheetsRegistry.
  const css = sheetsRegistry.toString()

  // Send the rendered page back to the client.
  res.send(renderFullPage(html, css))
}

无法弄清楚我错过了什么。我认为这可能是由于服务器端的某些原因,但无法弄清楚。

我已经读到这可能是由于历史组件造成的。但是,我已经看到了仅使用 BrowerRouter 的示例。(例如https://github.com/jsmegatools/React-online-course/tree/master/Lesson-2

谢谢!

【问题讨论】:

标签: javascript reactjs express react-router material-ui


【解决方案1】:

您需要正确设置它。他们两个彼此不同。 React 是客户端应用,而 Express 是服务器应用。

查看Sandeep Raveesh's post,并尝试boilerplate。它可能会帮助您理解它。

【讨论】:

  • 我建议将相关的 sn-ps 放在答案中,否则它会被标记为仅链接的答案,这将被删除。
  • 知道了。谢谢老兄。
【解决方案2】:

@Tholle 的回答帮助我解决了问题。

https://reacttraining.com/react-router/web/guides/server-rendering

【讨论】:

    猜你喜欢
    • 2018-07-20
    • 2018-07-16
    • 2021-01-06
    • 2019-04-28
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    相关资源
    最近更新 更多