升级后无法让反应路由器工作

Posted

技术标签:

【中文标题】升级后无法让反应路由器工作【英文标题】:Cannot get react-router to work after upgrade 【发布时间】:2017-08-04 06:05:51 【问题描述】:

我一直致力于将我们的应用程序从 React.js 0.13 升级到 15.4.2 以及围绕它的依赖项。我可能已经接近了,但在 4 天 50 小时后,我终于走到了尽头,我最后的希望。

在升级中,react-router 升级到版本 4.0.0,每个文档和教程以及堆栈溢出问题都显示了如何编写路由器(都一样,所以必须是正确的)但是,当我这样做时它总是失败。要么说历史是必需的属性,要么当我通过示例添加它时,它仍然显示为未定义和错误。

这是我们的 index.js 和路由器。

任何人都可以看到我没有正确理解的地方吗?谢谢

从“反应”导入反应;

// material ui
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Theme from './styles/theme.js';

import Header from './components/header.jsx';
import Home from './views/home.jsx';

import CaseController from 'controllers/caseController';
import LoginController from 'controllers/loginController';
import XController from 'controllers/xController';
import PredefinedSearchAssetCasesController from 'controllers/predefinedSearchAssetCasesController';
import PredefinedSearchCaseLabelsController from 'controllers/predefinedSearchCaseLabelsController';
import DeepSearchController from 'controllers/deepSearchController';
import NamesAndAddressController from 'controllers/namesAndAddressController';
import AccountListing from 'controllers/accountListingController';

import LoginStore from 'stores/loginStore';
import LoginActions from 'actions/loginActions';
import UtcStore from 'stores/utcStore';
import UtcActions from 'actions/utcActions';

import ErrorHandler from 'components/errorHandler';
import DialogMessageHandler from 'components/dialogMessageHandler';
import ConfirmationDialogHandler from 'components/confirmationDialogHandler';

// routing related
import  render  from 'react-dom';
import  Router, Route, DefaultRoute, Link, hashHistory, browserHistory  from 'react-router';

import versionNumber from 'raw-loader!../.version';

var App = React.createClass (

  childContextTypes: 
    muiTheme: React.PropTypes.object
  ,

  getChildContext() 
    return 
      muiTheme: MuiThemeProvider.get()
    ;
  ,

  componentWillMount() 
    //ThemeManager.setTheme(Theme);
    // TODO: consolidate into one request using /utc endpoint
    if (_.isEmpty(UtcStore.claimUtcList)) 
      UtcActions.getClaimUtcList();
    
    if (_.isEmpty(UtcStore.assetUtcList)) 
      UtcActions.getAssetUtcList();
    
    if (_.isEmpty(UtcStore.transferUtcList)) 
      UtcActions.getTransfers();
    
  ,

  componentDidMount() 
    LoginStore.addChangeListener(this.onLoginChange);
    if (!LoginStore.getLoginData())
      this.transitionTo('login');
      return false;
     else 
      LoginActions.checkToken();
    
  ,

  onLoginChange()
    if (!LoginStore.getLoginData())
      this.transitionTo('login');
    
  ,

  render() 

    console.log('VERSION: ', versionNumber);

    const styles = 
      root: 
        background: '#EEEEEE',
        paddingTop: 55 // see header.jsx menuHeight
      
    ;

    console.log('APP', this.context.router.getCurrentPath());

    let hideHeaderRoutes = ["/login"];
    let header = true;
    if (this.context.router.getCurrentPath().indexOf(hideHeaderRoutes) > -1)
      header = false;
      styles.root = undefined;
    

    return (
      <MuiThemeProvider muiTheme=Theme>
        <div style=styles.root>
          header ? <Header /> : 

          <ErrorHandler
            ref="errorHandler"
            />
          <DialogMessageHandler
            ref="dialogMessageHandler"
            />
          <ConfirmationDialogHandler
            ref="confirmDialogHandler"
            />
        </div>
      </MuiThemeProvider>
    );
  
);

render((
  <Router history=browserHistory>
    <Route component=App path="/">
      <DefaultRoute component=Home/>
      <Route path="home" component=Home />
      <Route path="case" component=CaseController />
      <Route path="case/:id/?:reverseToken?" component=CaseController /> /* reverseToken is optional path variable for going back to last state when we go to case screen*/
      <Route path="login" component=LoginController />
      <Route path="x" component=XController />
      <Route path="x/?:xDate?/?:xFromTime?/?:xToTime?/?:id?" component=XController />
      <Route path="namesAndAddress" component=NamesAndAddressController />
      <Route path="reconciliation/?:reverseToken?" component=AccountListing />
      <Route path="asset-cases/:predefinedQuery/:sortBy/?:reverseToken?" component=PredefinedSearchAssetCasesController />
      <Route path="case-labels/:predefinedQuery/:sortBy/?:reverseToken?" component=PredefinedSearchCaseLabelsController />
      <Route path="deep-search/:deepSearchQuery/:sortBy/openCasesOnly::openCasesOnly/assetCasesOnly::assetCasesOnly/searchType::searchType/?:reverseToken?" component=DeepSearchController />
    </Route>
  </Router>
), document.body);

【问题讨论】:

【参考方案1】:

History 对象似乎不再是 react-router 的一部分。所以,你 import Router, Route, DefaultRoute, Link, hashHistory, browserHistory from 'react-router'; 实际上并没有导入 hashHistory 或 browserHistory。

基于examples,获取历史对象的一种解决方案是安装history/createBrowserHistory package。

import  Router  from 'react-router'
import createBrowserHistory from 'history/createBrowserHistory'

const history = createBrowserHistory()

<Router history=history>
  <App/>
</Router>

【讨论】:

感谢詹姆斯的回答。我尝试过并从历史记录中得到错误,createBrowserHistory 指向 es.createBrowserHistory,其中有错误。而且看起来 react-router 也不再有 标签,所以我想我必须支持它的版本。而且 react-router 4 现在不再有静态路由,它有一个 beta 模块,但它太复杂了,以至于你无法理解它的文档。 你试过 BrowserRouter 吗? reacttraining.com/react-router/web/api/BrowserRouter【参考方案2】:

不幸的是,这个问题的答案是没有答案,react-router 4.00 需要 react-router-config 来像在早期版本中那样做静态路由。所以问题中上面的所有代码都是没有意义的。

【讨论】:

你查看this example了吗?它没有提到额外的模块。 basic example 也与您上面的配置非常相似。在经历了这个转换过程一段时间后,我可以与你的挑战联系起来:)。万事如意! 感谢 HazardouS,在第一个示例中,他们没有设置路由器的强制历史属性。第二个示例是使用最新的 1 周旧版本 4.0.0,我了解到它无法进行静态路由,除非它使用他们的 Alpha 版本的 react-router-config,它没有文档,我被告知他们认为 API 也会发生变化,因为它是 Alpha。所以我确实需要将我的升级降级到 3.0 版。 文档将在一段时间内赶上。可以看看你的回购吗? 使用withRouter hoc 在您需要的任何组件中注入上下文。 当你到达那里时,从 v3 迁移到 v4 应该会更容易。

以上是关于升级后无法让反应路由器工作的主要内容,如果未能解决你的问题,请参考以下文章

登录页面后反应路由器 v6 不会切换到主页:警告:无法对未安装的组件执行 React 状态更新

构建应用程序后反应路由器不起作用

反应路由抛出错误:无法读取浏览器路由器未定义的属性“推送”

反应嵌套路由无法正常工作

为啥在部署我的项目后卡住/空白页面?反应路由器 Dom |参数

反应路由器 - 无法传递存储