Update react-router and react-router-relay to v2.x from v1.x (Location “/” did not match any routes)

末鹿安然 提交于 2019-12-06 07:31:23

问题


I'm trying to update react-router to v2.6 and react-router-relay to v0.7 in my app but I'm struggling to follow the changelogs to address all breaking changes. I think I addressed all changes but I still can't make it work.

Warning: [react-router] Location "/" did not match any routes

Here is a step by step guide on what I did to address the changes. First I updated the npm modules.

My previous package.json where everything worked:

"dependencies": {
    "babel-polyfill": "^6.9.1",
    "babel-runtime": "^6.9.2",
    "graphiql": "0.7.3",
    "graphql": "^0.6.2",
    "history": "1.13.1",
    "isomorphic-fetch": "^2.1.1",
    "react": "^15.2.1",
    "react-addons-shallow-compare": "^15.2.1",
    "react-dom": "^15.2.1",
    "react-loader": "^2.0.0",
    "react-relay": "^0.9.2",
    "react-router": "1.0.0-rc3",
    "react-router-relay": "^0.7.0",
    "superagent": "^1.2.0"
  },
  "devDependencies": {
    "babel-core": "^6.11.4",
    "babel-eslint": "^6.1.2",
    "babel-jest": "^13.2.2",
    "babel-loader": "^6.2.4",
    "babel-plugin-add-module-exports": "^0.2.1",
    "babel-plugin-transform-runtime": "^6.9.0",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.11.1",
    "babel-preset-stage-0": "^6.5.0",
    "babel-preset-stage-1": "^6.5.0",
    "babel-preset-stage-2": "^6.11.0",
    "babel-relay-plugin": "^0.9.2",
    "jest-cli": "^12.1.1",
    "react-addons-test-utils": "^15.2.1",
    "webpack": "^1.13.1"
  },

My new package.json, where I'm getting errors:

"dependencies": {
    "babel-polyfill": "^6.9.1",
    "babel-runtime": "^6.9.2",
    "graphiql": "0.7.3",
    "graphql": "^0.6.2",
    "isomorphic-fetch": "^2.1.1",
    "react": "^15.2.1",
    "react-addons-shallow-compare": "^15.2.1",
    "react-dom": "^15.2.1",
    "react-loader": "^2.0.0",
    "react-relay": "^0.9.2",
    "react-router": "^2.6.0",
    "react-router-relay": "^0.13.3",
    "superagent": "^1.2.0"
  },
  "devDependencies": {
    "babel-core": "^6.11.4",
    "babel-eslint": "^6.1.2",
    "babel-jest": "^14.0.0",
    "babel-loader": "^6.2.4",
    "babel-plugin-add-module-exports": "^0.2.1",
    "babel-plugin-transform-runtime": "^6.9.0",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.11.1",
    "babel-preset-stage-0": "^6.5.0",
    "babel-preset-stage-1": "^6.5.0",
    "babel-preset-stage-2": "^6.11.0",
    "babel-relay-plugin": "^0.9.2",
    "jest-cli": "^12.1.1",
    "react-addons-test-utils": "^15.2.1",
    "webpack": "^1.13.1"
  },

I removed the history module because it is now a direct dependency of react-router. Once I installed the latest modules, I reloaded my page and got the following errors:

Error 1:

Warning: [react-router] It appears you have provided a deprecated history object to <Router/>, please use a history provided by React Router with import { browserHistory } from 'react-router' or import { hashHistory } from 'react-router'. If you are using a custom history please create it with useRouterHistory, see https://github.com/reactjs/react-router/blob/master/upgrade-guides/v2.0.0.md#using-history-with-router for details.

Error 2:

Warning: Failed context type: Invalid prop/context relay supplied to Relay(App), expected undefined to be an object conforming to the RelayEnvironment interface.

in Relay(App) (created by RouterContext)
in RouterContext (created by Router)
in Router

Error 3:

Warning: Failed context type: Required context route was not specified in Relay(App).

in Relay(App) (created by RouterContext)
in RouterContext (created by Router)
in Router

Error 4:

Uncaught Invariant Violation: RelayContainer: Relay(App) was rendered with invalid Relay context undefined. Make sure the relay property on the React context conforms to the RelayEnvironment interface.

The first error gives a handy link to the upgrade-guides for react-router, so I followed it and updated my app.js file accordingly.

Before my changes it looked this:

import babelPolyfill from 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import ReactRouterRelay from 'react-router-relay';
import Loader from 'react-loader';
import { Router, Route } from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';

import WelcomeQueries from './queries/WelcomeQueries';
import AppQueries from './queries/AppQueries';
import LandingQueries from './queries/LandingQueries';

import App from './components/app';
import Landing from './components/landing';

import './relay';

const renderProps = {
  renderLoading: () => <Loader />,
};

ReactDOM.render((
  <Router history={createBrowserHistory()} createElement={ReactRouterRelay.createElement}>
    <Route component={App} queries={AppQueries} {...renderProps}>
      <Route path="/myapp" component={Landing} queries={LandingQueries} {...renderProps} />
    </Route>
    <Route path="/myapp/tracks" component={Welcome} queries={WelcomeQueries} {...renderProps}/>
  </Router>
), document.getElementById('myapp-body'));

Attempt 1

Using the update guide to 2.x I've changed my app.js file to use a custom history like this:

import babelPolyfill from 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import ReactRouterRelay from 'react-router-relay';
import Loader from 'react-loader';

import { Router, Route, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'

import WelcomeQueries from './queries/WelcomeQueries';
import AppQueries from './queries/AppQueries';
import LandingQueries from './queries/LandingQueries';

import App from './components/app';
import Landing from './components/landing';

import './relay';

const renderProps = {
  renderLoading: () => <Loader />,
};

const appHistory = useRouterHistory(createHashHistory)({ queryKey: false })

ReactDOM.render((
  <Router history={appHistory} createElement={ReactRouterRelay.createElement}>
    <Route component={App} queries={AppQueries} {...renderProps}>
      <Route path="/myapp" component={Landing} queries={LandingQueries} {...renderProps} />
    </Route>
    <Route path="/myapp/tracks" component={Welcome} queries={WelcomeQueries} {...renderProps}/>
  </Router>
), document.getElementById('myapp-body'));

This then gives me the following error in the browser:

Error 5

Warning: [react-router] Location "/" did not match any routes

I believe that is the solution I want.. However I wasn't sure, so I also tried going the Browser (HTML5 pushState) History way and tried the following change:

Attempt 2

import babelPolyfill from 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import ReactRouterRelay from 'react-router-relay';
import Loader from 'react-loader';

import { Router, Route, browserHistory } from 'react-router'

import WelcomeQueries from './queries/WelcomeQueries';
import AppQueries from './queries/AppQueries';
import LandingQueries from './queries/LandingQueries';

import App from './components/app';
import Landing from './components/landing';

import './relay';

const renderProps = {
  renderLoading: () => <Loader />,
};

const appHistory = useRouterHistory(createHashHistory)({ queryKey: false })

ReactDOM.render((
  <Router history={browserHistory} createElement={ReactRouterRelay.createElement}>
    <Route component={App} queries={AppQueries} {...renderProps}>
      <Route path="/myapp" component={Landing} queries={LandingQueries} {...renderProps} />
    </Route>
    <Route path="/myapp/tracks" component={Welcome} queries={WelcomeQueries} {...renderProps}/>
  </Router>
), document.getElementById('myapp-body'));

When loading this, I get back errors 2, 3 and 4. I think Attempt 1 is the correct approach but I don't know what this error means and googling it, gave me tons of answers (1, 2, which linked me to 3 and even 4 with IndexRoute), which I tried but none of the answers worked.

My App.js file looks like this, just for reference:

import React from 'react';
import Relay from 'react-relay';
import Top from './top';

export class App extends React.Component {
  render() {
    return (
      <div>
        <Top viewer={this.props.viewer}/>
        {this.props.children}
      </div>
    );
  }
}

export default Relay.createContainer(App, {
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        ${Top.getFragment('viewer')}
      }
    `,
  },
});

I'm not 100% sure if this might be the reason but I know that react-router v2.0.0-rc6 had a breaking change with the top level Router export being removed but I don't really know what that means for me? Does that I can't use Router anymore? If so, what am I supposed to instead?

After days of research and trial and error, I'm giving up and hope that someone here can help. Any pointers in the right direction would be greatly appreciated.


回答1:


Finally got an answer to this question and had to add the following changes to make my code work again:

import babelPolyfill from 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import Loader from 'react-loader';

import Relay from 'react-relay';
import useRelay from 'react-router-relay';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import applyRouterMiddleware from 'react-router/lib/applyRouterMiddleware';

import WelcomeQueries from './queries/WelcomeQueries';
import AppQueries from './queries/AppQueries';
import LandingQueries from './queries/LandingQueries';

import App from './components/app';
import Landing from './components/landing';

import './relay';

ReactDOM.render((
  <Router 
    history={browserHistory} 
    render={applyRouterMiddleware(useRelay)} 
    environment={Relay.Store}>

    <Route 
      component={App} 
      queries={AppQueries} 
      render={({ props }) => props ? <App {...props} /> : <Loader />}>

      <Route 
        path="/myapp" 
        component={Landing} 
        queries={LandingQueries} 
        render={({ props }) => props ? <Landing {...props} /> : <Loader />} />
    </Route>

    <Route 
      path="/myapp/tracks" 
      component={Welcome} 
      queries={WelcomeQueries} 
      render={({ props }) => props ? <Welcome {...props} /> : <Loader />} />

  </Router>
), document.getElementById('myapp-body'));

Maybe this will help someone else :)



来源:https://stackoverflow.com/questions/38645808/update-react-router-and-react-router-relay-to-v2-x-from-v1-x-location-did-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!