首页 文章

新版本的反应路由器不能与redux一起使用

提问于
浏览
3

也许这个问题是因为反应路由器的新版本有几天,但我一直在阅读这个问题,我想澄清发生了什么 . 我正在使用最新版本的react路由器,我想通过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 (dispatch)

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

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

3 回答

  • 1

    而不是BrowserRouter,使用react-router-redux库中的ConnectedRouter:

    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'));
    
  • 0

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

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

    使用HTML5历史记录API(pushState,replaceState和popstate事件)的<Router>,以使您的UI与URL保持同步 .

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

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

    我相信以上内容将解决您的问题 . 如果你想要我,我可以分享一个有效的例子,但我的解决方案与你的解决方案非常相似,但我的上述评论除外 .

    我希望这有帮助 .

  • 0

    这对我有用 .

    我使用了"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")
        );
    

    我希望这对你也有用 .

    快乐的编码!

相关问题