【问题标题】:New version react router doesn't work with redux新版本的反应路由器不适用于 redux
【发布时间】:2017-04-16 18:00:11
【问题描述】:

也许这个问题是因为新版本的反应路由器有几天,但我一直在阅读这个问题,我想澄清发生了什么。我正在使用最新版本的反应路由器,我想通过 redux 进行路由。我按照 redux 路由器模块文档中列出的步骤:https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux,但在执行时收到此错误:(我知道问题出在服务器渲染中)

Invariant Violation: Browser history needs a DOM

这是我的代码(重要部分):

server.js

import { Provider } from 'react-redux';
import store from './store';

lisaApp.get('*', function (req, res) {
  const context = {};

  const html = renderToString(
    <Provider store={store}>
      <MuiThemeProvider muiTheme={getMuiTheme()}>
        <StaticRouter location={req.url} context={context}>
          <Routes />
        </StaticRouter>
      </MuiThemeProvider>
    </Provider>,
  );

  res.setHeader('Content-Type', 'text/html');

  if (context.url) {
    res.writeHead(301, {
      Location: context.url,
    });
    res.end();
  }

  res.write(
    renderToStaticMarkup(<Layout title={req.title} content={html} />),
  );

  res.end();
}

client.js

import { Provider } from 'react-redux';
import createHistory from 'history/createBrowserHistory';
import { BrowserRouter } from 'react-router-dom';
import store from './store';

render((
  <Provider store={store}>
    <MuiThemeProvider muiTheme={getMuiTheme()}>
      <BrowserRouter history={createHistory()}>
        <Routes />
      </BrowserRouter>
    </MuiThemeProvider>
  </Provider>),
  document.getElementById('app'));

store.js

import { createStore, combineReducers, applyMiddleware } from 'redux'
import createHistory from 'history/createBrowserHistory'
import { ConnectedRouter, routerReducer, routerMiddleware, push } from 'react-router-redux'
import thunk from 'redux-thunk';

import reducer from './reducer';

const history = createHistory()
const middlewareHistory = routerMiddleware(history)

const store = createStore(
  combineReducers({
    reducer,
    router: routerReducer
  }),
  applyMiddleware(
    middlewareHistory,   
    thunk
  )
);

export default store;

component.js(调度)

const mapDispatchToProps = dispatch => {
  return {
    onNavigateTo(dest) {
      dispatch(push(dest));
    }
  };
};

显然,来自我的组件的调度永远不会被调用。任何人都可以澄清我哪里错了吗?或者这个功能可能还没有在反应路由器 redux 模块中实现?提前谢谢。

【问题讨论】:

    标签: javascript reactjs redux react-router


    【解决方案1】:

    使用 react-router-redux 库中的 ConnectedRouter 代替 BrowserRouter

    import { Provider } from 'react-redux';
    import createHistory from 'history/createBrowserHistory';
    import { ConnectedRouter } from 'react-router-redux';
    import store from './store';
    
    render((
        <Provider store={store}>
            <MuiThemeProvider muiTheme={getMuiTheme()}>
                <ConnectedRouter history={createHistory()}>
                    <Routes />
                </ConnectedRouter>
            </MuiThemeProvider>
        </Provider>),
        document.getElementById('app'));
    

    【讨论】:

    • 嗨帕特里克,首先我要感谢您的回答,我尝试了您的建议但它不起作用,我认为是因为问题与服务器渲染有关,因为客户端很好。问题是因为客户端和服务器之间的“存储”是相同的。
    • 啊,好的,我错过了你的问题部分,你说问题与服务器上的渲染有关。在服务器上渲染时,应该使用 StaticRouter。我有类似的设置,并使用不同的脚本在服务器端和客户端进行初始化。服务器端使用StaticRouter,客户端使用ConnectedRouter。
    • 是的,正如您在我的代码中看到的,我在服务器端使用 StaticRouter,但是 Provider 中的“存储”是由服务器端和客户端共享的,所以,因为当我编译应用程序时会显示错误。你有新版本的 react-router.dom 的实现吗?
    • 我修复了这个问题以避免错误。我使用历史库中的 createBrowserHistory 模块和同一个库中的 createMemoryHistory 模块。但是现在,调度没有执行“推送”操作,但我知道它被调用了,因为记录器向我显示了调用的数据
    【解决方案2】:

    几天前我遇到了同样的问题。在您的 BrowserRouter 中,您手动创建并传递一个 browserHistory 对象。然后,每当您需要访问历史对象时,您都会导入它,就像它发生在您的 store.js 中一样,它在服务器和客户端之间共享。但是,在服务器上没有 DOM,因此出现错误。

    我通过不手动创建历史对象来解决此问题,因为您使用的是 BrowserRouter,所以不需要这样做。如文档中所述,BrowserRouter 是:

    使用 HTML5 历史 API(pushState、replaceState 和 popstate 事件)的 使您的 UI 与 URL 保持同步。

    无需在需要时手动导入历史记录,只需使用方便的 withRouter 高阶组件即可。这样,在您的道具中,您不仅可以访问历史记录,还可以访问最近的 匹配项。阅读更多关于它的信息here

    关于你关于调度的最后一点,你是对的,它没有被调用。每当你通过 react-redux 的 connect 创建一个组件时,记得用 withRouter 高阶组件包装它。阅读更多关于它的信息here

    我相信以上内容会解决您的问题。如果您愿意,我可以分享一个工作示例,但我的解决方案与您的解决方案非常相似,除了我上面的 cmets。

    我希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      这对我有用。

      我使用了“react-router-dom”库中的 ConnectRouter。除了它,我还使用了“react-router-dom”库中的 BrowserRouter。 **现在我可以愉快地使用 React+Redux+Routing。

          import React from "react";
          import ReactDOM from "react-dom";
          import { BrowserRouter } from "react-router-dom";
          import { Provider } from "react-redux";
          import { createStore } from "redux";
          import rootReducer from "./reducers";
          import App from "./App";
          import { connectRouter } from "connected-react-router";
          import createHistory from "history/createBrowserHistory";
          export const history = createHistory();
          const store = createStore(connectRouter(history)(rootReducer));
          ReactDOM.render(
            <Provider store={store}>
              <BrowserRouter>
                <App />
              </BrowserRouter>
            </Provider>,
            document.getElementById("root")
          );
      

      我希望这也对你有用。

      编码愉快!!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-03
        • 1970-01-01
        • 2022-07-24
        • 2017-12-16
        • 2016-08-24
        • 2021-02-15
        • 2018-01-14
        • 2020-11-01
        相关资源
        最近更新 更多