"Не используйте Route или withRouter() вне Router при работе с react-router 4 и styled-components в React"
Я пытаюсь создать свой первый портфолио-сайт, но застрял с маршрутизацией, используя react-router-dom версии 4.2.2 и styled-components версии 2.2.3.
Я получаю сообщение об ошибке: "You should not use Route or withRouter() outside a Router".
Я также пробовал использовать Link вместо NavLink, но тоже получил ошибку: "You should not use Link outside a Router".
Кто-нибудь, помогите, пожалуйста.
navigationBar.js
import React, { Component } from 'react';
import { NavigationContainer, NavItem } from './navigationBar.style';
class NavigationBar extends Component {
render() {
return (
<NavigationContainer>
<NavItem to="/">Home</NavItem>
<NavItem to="/projects">Project</NavItem>
</NavigationContainer>
);
}
}
export default NavigationBar;
navigationBar.style.js
import styled from 'styled-components';
import { Flex, Div } from 'theme/grid';
import { NavLink } from 'react-router-dom';
export const NavigationContainer = styled(Flex)`
position: fixed;
right: 20px;
top: 0.5em;
font-size: 1em;
`;
export const NavItem = styled(NavLink)`
position: relative;
padding-left: 10px;
cursor: pointer;
`;
Как мне исправить эту проблему с маршрутизацией?
5 ответ(ов)
Убедитесь, что основной код рендеринга React обернут в Router. Например, если вы используете react-dom, вам нужно обернуть ваше приложение в BrowserRouter. Если это проект Udacity, обычно это файл index.js.
Вот пример кода:
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
Таким образом, ваше приложение сможет использовать маршрутизацию.
Вы используете NavLink вне BrowserRouter или HashRouter (в зависимости от того, что вы используете).
Вы сами об этом сказали:
Вы не должны использовать Link вне Router.
Убедитесь, что ваша структура выглядит примерно так:
// Отрисовка App или что-то другое
render() {
return (
<BrowserRouter>
<NavigationBar />
{`и все, что вы там делаете`}
</BrowserRouter>
);
}
Вы всегда должны рендерить их внутри Router.
Проблема, о которой вы говорите, действительно часто возникает из-за того, что в проекте использовано несколько копий React, что может привести к предупреждениям "Invalid hook call". Это связано с тем, что React может не правильно идентифицировать состояние компонентов, если они используют разные инстансы библиотеки.
Как вы упомянули в своем вопросе, причина вроде бы в использовании npm link
, когда ваше приложение пытается использовать React из разных проектов, например "react-app" и "react-app-components". Это может привести к конфликтам, особенно при публикации в npm repository
, когда ошибка исчезает, так как используется только одна версия React.
Что касается вашего решения: удаление зависимостей react
и react-router-dom
из файла package.json
и повторная установка зависимостей — это хороший способ избежать дублирования этих библиотек. Когда вы оставляете только зависимости, связанные с типами @types/*
, это позволяет использовать TypeScript без необходимости включать сами библиотеки в зависимости вашего проекта.
Ваш файл package.json
до и после изменений показывает правильный подход:
Перед:
{
//...
"devDependencies": {
//...
"react": "^16.13.1",
"react-router-dom": "^5.2.0",
//...
},
"peerDependencies": {
"react": "^16.13.1",
"react-router-dom": "^5.2.0"
}
}
После:
{
//...
"devDependencies": {
//...
// Здесь удалены "react" и "react-router-dom"
},
"peerDependencies": {
"react": "^16.13.1",
"react-router-dom": "^5.2.0"
}
}
Таким образом, вы оставляете только peerDependencies
, что обусловлено тем, что другие пакеты (например, react-app-components
) теперь будут отвечать за установку React. Это помогает избежать проблемы с дублированием и улучшает совместимость компонентов.
Если у вас остались вопросы или вы столкнулись с другими проблемами, не стесняйтесь задавать их!
Это может быть результатом путаницы в node_modules
для мультирепозиторных проектов с различными подходами интеграции.
Самый простой способ избежать подобных проблем — это иметь только одну папку node_modules
для всех проектов, интегрированных в одно приложение. В противном случае некоторые подпроекты могут использовать разные версии одной и той же библиотеки (например, React или Router и т. д.), которые могут быть несовместимы друг с другом на уровне внутренних структур данных (реактивные контексты и так далее), что приводит к таким проблемам.
Проблема решается при использовании <Router>
, просто разместите его снаружи </Router></AppProvider>
. Вот пример кода:
<BrowserRouter>
<Switch>
{/* Пример маршрута */}
<Route path="/index" render={(props) => <Index {...props} />} />
</Switch>
</BrowserRouter>
Убедитесь, что вы правильно организовали структуру компонентов, чтобы избежать потенциальных проблем с контекстом, который предоставляет ваш AppProvider
.
Как программно выполнять навигацию с помощью React Router?
React-router URLs не работают при обновлении страницы или ручном вводе адреса
Обнаружена ошибка: Невозможное нарушение: Неверный тип элемента: ожидался строковый тип (для встроенных компонентов) или класс/функция, но получен объект
Storybook с react-router: Не используйте <Link> вне <Router>
Использование IndexRoute в react-router v4 с React