Я использую react-router-dom для маршрутизации в своем React приложении. Часть моего приложения извлечена в другой пакет. Список зависимостей выглядит так:
./приложение/приборная панель/package.json
{
"dependencies": {
"@app/components": "^1.0.0",
"react": "^16.8.5",
"react-dom": "^16.8.5",
"react-router-dom": "^5.0.0"
}
}
./приложение/компоненты/package.json
{
"peerDependencies": {
"react-router-dom": "^5.0.0"
}
}
Когда я использую компоненты из @app/components, которым требуются компоненты из react-router-dom, я получаю следующие ошибки:
Uncaught Error: Invariant failed: You should not use <Route> outside a <Router>
The above error occurred in the <Context.Consumer> component:
Uncaught (in promise) Error: Invariant failed: You should not use <Route> outside a <Router>
Почему выдает эту ошибку? В App.js я использую BrowserRouter
import React, { Suspense } from 'react';
import { Switch, Route } from 'react-router-dom';
import { Placeholder } from '@app/components';
const Auth = React.lazy(() => import(/* webpackPrefetch: true */ './pages/Auth'));
const Index = React.lazy(() => import(/* webpackPrefetch: true */ './pages/Index'));
const App = () => (
<Suspense fallback = {<Placeholder />}>
<Switch>
<Route path = "/auth" component = {Auth} />
<Route path = "/" component = {Index} />
</Switch>
</Suspense>
);
export default App;
клиент.jsx
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'),
);





Вам также нужно импортировать именованный экспорт Router из react-router-dom и обернуть его вокруг компонентов коммутатора/маршрута.
const App = () => (
<Router>
<Suspense fallback = {<Placeholder />}>
<Switch>
<Route path = "/auth" component = {Auth} />
<Route path = "/" component = {Index} />
</Switch>
</Suspense>
</Router>
);
Я оборачиваю все свое приложение в client.jsx
Это решение сработало и для меня, хотя я немного удивлен. Как и в OP, у меня есть это Router в моем клиентском коде.
У вас есть висящая запятая в конце вызова рендеринга после document.getElementById('root').
render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'),
);
Не проблема. JS это позволяет.
Проблема с 2 экземплярами React
Попытка отобразить несколько экземпляров <BrowserRouter> вызвала это исключение в моем коде, спасибо за подсказку!
@rodurico У меня такая же проблема. Как вы это решили?
@SawanPatodia Мне пришлось перерисовать корневой компонент. У вас должен быть один <Router> внутри одного <BrowserRouter> во всем проекте.
Я решил эту загадочную ошибку, удалив зависимость «react-router-dom» из MyComponent. Я удалил «node_modules/react-router-dom» и из «package.json» Мое приложение структурировано следующим образом:
AppFolder
├── README.md
├── build
├── node_modules
│ ├── react-router-dom
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── index.js
├── redux
│ ├── reducers.js
│ └── store.js
└── serviceWorker.js
MyComponent
├── README.md
├── dist
├── node_modules
│ ├── react-router-dom
├── package-lock.json
├── package.json
├── rollup.config.js
└── src
├── index.js
├── styles.css
└── test.js
Это исходный код для App.js
import MyComponent from 'MyComponent'
export default App(){
return (
<div className = "App">
<HashRouter>
<div>
<header className = "App-header">
</header>
<Route path = "/home" component = {MyComponent}/>
</div>
</HashRouter>
</div>)
}
Это экспорт для MyComponent
export default withRouter(MyComponent);
Если в папке компонента оставить 'react-router-dom', появится ошибка.
Проблема для меня заключалась в том, что я установил и react-router-dom, и react-router. Я удалил последний, и моя проблема была решена.
Я получил это во время тестирования моего компонента, который связан с проектом (используя npm link) и из-за этого react-router-dom загружен более одного раза, в моем случае работает следующее решение:
Внутри webpack.config.js я добавил:
resolve: {
alias: {
'react-router-dom': path.resolve('./node_modules/react-router-dom')
}
}
Если кто-то придет сюда с той же проблемой с <Link> вместо <Route>, как у меня, мне нужно было добавить как react-router, так и react-router-dom в качестве псевдонимов, чтобы это работало, даже если у меня нет react-router в качестве зависимости .
'Будьте здоровы!! Это также происходит при работе с локальными пакетами, которые имеют зависимость react-router-dom.
У меня была аналогичная проблема с компонентом Redirect. Оказалось, что я вызывал Redirect из 'react-router', а не 'react-router-dom'.
Error: Invariant failed: You should not use <Redirect> outside a <Router>
В моем случае эта ошибка была вызвана смешением использования вещей (withRouter, MemoryRouter) из react-router и react-router-dom. Используя только вещи из react-router-dom, инвариантная ошибка исчезла. Надеюсь, это поможет кому-нибудь.
Вы должны включить тег Route, тег Link внутри тега Router.
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const Home = () => {
return (
<div>
<p>Home</p>
</div>
);
};
const About = () => {
return (
<div>
<p>About</p>
</div>
);
};
const Contact = () => {
return (
<div>
<p>Contact</p>
</div>
);
};
class App extends Component {
render() {
return (
<Router>
<div>
<h1>W3Adda - Simple SPA</h1>
<nav>
<ul>
<li>
<Link to = "/">Home</Link>
</li>
<li>
<Link to = "/about">About</Link>
</li>
<li>
<Link to = "/contact">Users</Link>
</li>
</ul>
</nav>
<Route path = "/" exact component = {Home} />
<Route path = "/about" component = {About} />
<Route path = "/contact" component = {Contact} />
</div>
</Router>
);
}
}
export default App;
Я решил эту проблему, изменив:
import {Route, Switch} from "react-router";
к
import {Route, Switch} from "react-router-dom";
просто добавь -дом.
У меня была такая же проблема с импортом Redirect из «реагирующего маршрутизатора».
Я решаю эту ошибку, заключая родительский компонент в Router.
Перед устранением ошибки
<Header />
<div className = "col-md-12 pd-0-0">
<div className = "row">
<Sidebar />
<div className = "col-sm-10 col-md-10 pd-0-0" style = {style}>
<Router>
<Switch>
<Route path = "/dashboard/check-in" component = {CheckIn} />
<Route path = "/dashboard/deals" component = {Deals} />
<Route path = "/dashboard/events" component = {Events} />
<Route path = "/dashboard/invoice" component = {Invoice} />
<Route path = "/dashboard/notification" component = {Notification} />
<Route path = "/dashboard/profile" component = {Profile} />
<Route path = "/dashboard/redemption" component = {Redemptions} />
<Route path = "/dashboard/restriction-management" component = {RestrictionManagement} />
</Switch>
</Router>
</div>
</div>
</div>
После решения ошибки
<Router>
<Header />
<div className = "col-md-12 pd-0-0">
<div className = "row">
<Sidebar />
<div className = "col-sm-10 col-md-10 pd-0-0" style = {style}>
<Switch>
<Route path = "/dashboard/check-in" component = {CheckIn} />
<Route path = "/dashboard/deals" component = {Deals} />
<Route path = "/dashboard/events" component = {Events} />
<Route path = "/dashboard/invoice" component = {Invoice} />
<Route path = "/dashboard/notification" component = {Notification} />
<Route path = "/dashboard/profile" component = {Profile} />
<Route path = "/dashboard/redemption" component = {Redemptions} />
<Route path = "/dashboard/restriction-management" component = {RestrictionManagement} />
</Switch>
</div>
</div>
</div>
</Router>
У меня была та же проблема с моим приложением Create React при запуске тестов, и я решил ее, поместив <Router></Router внутрь App.js вместо Index.js, как я всегда делал.
До:
Index.js
ReactDOM.render(
<React.StrictMode>
<GlobalStyle />
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById('root')
);
App.js
return (
<div className = "App">
<Header />
<Route path = "/blabla" component = {Whatever}
</div>
)
После:
Индекс.js:
ReactDOM.render(
<React.StrictMode>
<GlobalStyle />
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js:
return (
<div className = "App">
<Router>
<Header />
<Route path = "/blabla" component = {Whatever}
</Router>
</div>
)
Я решил эту проблему, просто импортировав BrowserRouter из react-router-dom в index.js и добавив:
<BrowserRouter>
<App>
</BrowserRouter>
в пределах:
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root'));
Использование тега <Link> в компоненте, который не имеет импорта, может привести к этой ошибке, попробуйте импортировать BrowserRouter из 'react-router-dom'
import {BrowserRouter , Link} from 'react-router-dom';
затем убедитесь, что ваши связанные теги заключены в тег
На самом деле проблема была в вашем корневом компоненте, где вы выполняете маршрутизацию, вы не должны добавлять какой-либо компонент за пределами тега Router в компонент, этот компонент ожидает только один или несколько компонентов, обернутых Route под Router в этих компонентах.
неправильный код (но он будет работать, но вы создаете ошибку) -
function App() {
return (
<div className = "App">
<Header/>
<Router>
<Switch>
<Route path = "/" exact>
<Home />
</Route>
</Switch>
</Router>
</div>
);
}
Я удаляю только <Header/> , это решило проблему.
написать код -
function App() {
return (
<div className = "App">
<Router>
<Switch>
<Route path = "/" exact>
<Home />
</Route>
</Switch>
</Router>
</div>
);
}
Мне удалось решить проблему, удалив <BrowserRouter> из router.js и включив его в app.js
export default function Routes() {
return (
<Switch>
<Route path = "/" exact component = {Home} />
<Route path = "/book" component = {Book} />
<Route path = "/client" component = {Client} />
<Route path = "/rent" component = {Rent} />
<Route path = "/dash" component = {Dash} />
</Switch>
);
}
function App() {
return (
<div>
<BrowserRouter>
<Header></Header>
<Routes/>
</BrowserRouter>
</div>
);
}
Используйте Маршрутизатор вне ваших компонентов. Оберните все компоненты внутри Маршрутизатор, после чего вы сможете использовать Связь в своих компонентах.
импортировать {BrowserRouter as Router, Route, Switch} из 'react-router-dom';
<Router>
<Appbar />
<Switch>
<Route exact path = "/" component = {Home} />
<Route path = "/mac" exact component = {Mac} />
</Switch>
<Footer />
</Router>
Я не уверен, что это хорошая практика, чтобы обернуть роутер таким образом.
Я решил эту проблему, импортировав
import {BrowserRouter as Router, Route} from 'react-router-dom';
и завернул все компоненты Route под компонент Router
<Router>
<Route exact path='/' component = {HomePage} />
</Router>
У меня была похожая проблема при попытке заменить представления Rails в приложении Solidus.
Решение для меня состояло в том, чтобы отредактировать соперничество, чтобы использовать React Router, который я только что добавил, но, по-видимому, не полностью настроил.
Например, я отредактировал views/spree/home/index.html из:
<%= javascript_pack_tag 'application' %>
<%= react_component("Home/Index") %>
к:
<%= javascript_pack_tag 'application' %>
<%= react_component("Routes") %>
Для большей справки, вот мой javascript/components/Route.js:
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import Home from "./Home/Index";
import Product from "./Products/Show";
class Routes extends React.Component {
render() {
return (
<Router>
<Route exact path = "/" component = {Home} />
<Route path = "/products/:slug" component = {Product} />
</Router>
);
};
};
export default Routes;
У меня была эта проблема во время тестирования, и я решил ее, обернув тестовый компонент маршрутизаторами.
import React from 'react';
import ReactDom from 'react-dom';
import Header from '../components/Header/Header';
import { BrowserRouter } from 'react-router-dom';
it('renders Header without crashing', () => {
const div = document.createElement('div');
ReactDom.render(
<BrowserRouter>
<Header />
</BrowserRouter>,
div);
ReactDom.unmountComponentAtNode(div);
});
Jest, Enzyme: Invariant Violation: You should not use or , To test a component (with Jest) that contains and withRouter you need to import Router in you test, not in your component import { BrowserRouter as Invariant Violation: You should not use or withRouter() outside a According to react router 4 docs, the components are considered valid, where I can create components composed of s, then import them into another component and place inside a .
Спасибо. Это как раз то, что мне нужно для тестирования.
Разве вы не должны использовать <MemoryRouter> для тестов?
просто измените «реагировать-маршрутизатор» на «реагировать-маршрутизатор-дом»
import {Route} from "react-router";
к
import {Route} from "react-router-dom";
Это сработало отлично!
У меня была аналогичная ситуация с основным приложением, созданным с помощью CRA и библиотеки компонентов. У нас есть два экземпляра react-router-dom, работающих независимо. Компонент из библиотеки использует <Link>, а родительское приложение — <Router>.
Вдохновленный ответом @Pavel, я обнаружил, что проблему можно решить, добавив псевдонимы. Если вы используете webpack, вы можете изменить способ разрешения модуля react-router-dom. Вы можете перезаписать порядок по умолчанию, в котором веб-пакет будет искать ваши зависимости, и сделать node_modules вашего родительского приложения более приоритетным, чем порядок разрешения модулей узла компонента:
псевдонимы.js
const fs = require('fs');
const path = require('path');
const directory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(directory, relativePath);
module.exports = {
react: resolveApp('node_modules/react'),
'react-router-dom': resolveApp('node_modules/react-router-dom'),
};
которые используются config-override.js для переопределения настроек CRA по умолчанию:
const { addWebpackAlias, override, removeModuleScopePlugin } = require('customize-cra');
const aliases = require('./aliases');
module.exports = override(removeModuleScopePlugin(), addWebpackAlias(aliases));
или для webpack.config.js (если это не CRA):
resolve: {
alias: {
"react-router-dom": path.resolve(appFolder, "node_modules", "react-router-dom"),
}
}
Если вы используете GatsbyJS и получаете эту ошибку, просто измените свой
import { Link } from "react-router-dom";
к
import { Link } from 'gatsby';
Самый простой ответ находится прямо в официальном документе от reactstrap для Navbar, см. этот сайт https://reactstrap.github.io/components/navbar/
Они руководствовались тем, что нам нужно использовать этот импорт
import {NavLink} from 'reactstrap';
Если кто-то добавляет теги
<Router>в попытке исправить это, обратите внимание, что вы должны импортироватьBrowserRouter as Router, чтобы это работало.