Использование IndexRoute в react-router v4 с React
Я учусь работать с React, используя онлайн-уроки.
У меня есть базовый пример использования React Router:
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/home" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact}/>
</Route>
</Router>
И вот мой компонент App:
class App extends React.Component {
render() {
return (
<div>
<ul>
<li><Link to="home">Home</Link></li>
<li><Link to="about">About</Link></li>
<li><Link to="contact">Contact</Link></li>
</ul>
{this.props.children}
</div>
)
}
}
export default App;
Однако у меня возникла проблема с использованием IndexRoute, так как он ничего не отображает. Я поискал модуль react-router-dom v4 на npm, и там нет IndexRoute. Вместо этого используется следующий код:
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact}/>
</div>
</Router>
Таким образом, как я могу отобразить два компонента для одного пути?
5 ответ(ов)
UPDATE
react-router-4
изменился, и теперь у него нет свойства children
. Тем не менее, с помощью компонента Route
вы можете отрисовать любые компоненты, которые соответствуют заданному пути.
<Router>
<div>
<ul>
<li><Link to="/">Главная</Link></li>
<li><Link to="/about">О нас</Link></li>
<li><Link to="/contact">Контакты</Link></li>
</ul>
<hr/>
{/* Все 3 компонента ниже будут отрисованы на главной странице */}
<Route exact path="/" component={Home}/>
<Route exact path="/" component={About}/>
<Route exact path="/" component={Contact}/>
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact}/>
</div>
</Router>
Это означает, что если вам нужен обертка, вы можете реализовать ее внутри самого компонента.
Структура маршрутизации в react-router
изменилась, и теперь IndexRoute
больше не используется. Вместо этого вы можете использовать Route
с атрибутом exact
, чтобы указать, что маршрут должен точно соответствовать пути. К примеру:
<Route exact path="/" component={Home}/>
Этот код эквивалентен прежнему IndexRoute
:
<IndexRoute component={Home}/>
Вот пример того, как можно использовать Switch
для организации маршрутов:
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
</Switch>
Здесь Switch
гарантирует, что будет рендериться только один дочерний компонент.
Также стоит обратить внимание на стилизацию с использованием таких компонентов, как Fade
. Например:
<Fade>
<Switch>
<Route/>
<Route/>
</Switch>
</Fade>
Это позволяет плавно переходить между маршрутами, однако если Fade
будет использоваться с несколькими дочерними элементами, это может усложнить управление переходами, так как один из компонентов может возвращать null
.
Если вам нужно больше информации о новых изменениях, вы можете взглянуть на обсуждение в репозитории GitHub и документацию React Router.
Подобный вопрос может возникнуть на StackOverflow, и вот как можно ответить на него, переведя на русский язык:
Не знаю, поможет ли это, но вот коды, которые я использовал.
Структура файлов:
src
├── index.js
└── app (папка)
├── components (папка)
│ ├── Header.js
│ ├── Home.js
│ ├── Root.js
│ └── User.js
└── index.js
src/app/index.js:
import React, { Component } from "react";
import { render } from "react-dom";
import { browserHistory } from "react-router";
import { BrowserRouter as Router, Route, IndexRoute } from "react-router-dom";
import Root from "./components/Root";
import Home from "./components/Home";
import User from "./components/User";
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<div>
<Root>
<Route exact path={"/"} component={Home} />
<Route path={"/user"} component={User} />
<Route path={"/home"} component={Home} />
</Root>
</div>
</Router>
);
}
}
render(<App />, window.document.getElementById("app"));
src/app/components/Root.js:
import React, { Component } from "react";
import { render } from "react-dom";
import Header from "./Header";
class Root extends Component {
render() {
let renderData;
renderData = this.props.children;
return (
<div>
<div className="container">
<div className="row">
<div className="col-xs-10 col-xs-offset-1">
<Header />
</div>
</div>
<div className="row">
<div className="col-xs-10 col-xs-offset-1">
{renderData}
</div>
</div>
</div>
</div>
);
}
}
export default Root;
src/app/components/Home.js:
import React, { Component } from "react";
class Home extends Component {
render() {
return (
<div>
<p>{this.props.isExist}</p>
<h2>Home</h2>
</div>
);
}
}
export default Home;
src/app/components/User.js:
import React, { Component } from "react";
class User extends Component {
render() {
return (
<div>
<h3>The user page</h3>
<p>User ID:</p>
</div>
);
}
}
export default User;
webpack.config.js:
var webpack = require("webpack");
var path = require("path");
var DIST_DIR = path.resolve(__dirname, "dist");
var SRC_DIR = path.resolve(__dirname, "src");
var config = {
entry: SRC_DIR + "/app/index.js",
output: {
path: DIST_DIR + "/app",
filename: "bundle.js",
publicPath: "/app/"
},
module: {
loaders: [
{
test: /\.js?/,
include: SRC_DIR,
loader: "babel-loader",
query: {
presets: ["react", "es2015", "stage-2"]
}
}
]
}
};
module.exports = config;
Если у вас есть какие-либо проблемы или вопросы относительно этого кода, пожалуйста, уточните, и я с радостью помогу!
В вашем коде есть несколько моментов, которые стоит исправить. Во-первых, вы используете несколько однотипных маршрутов для компонента Home
, что может привести к путанице. Также можно оптимизировать ваш код, чтобы избежать дублирования. Вот пример, как можно улучшить ваш код:
<Router history={browserHistory}>
<div>
<Root>
<Redirect from="*" to="/home"/>
<Route exact path="/home" component={Home}/>
<Route path="/user" component={User} />
</Root>
</div>
</Router>
Обратите внимание на следующие изменения:
- Убрано дублирование маршрутов для
Home
. Теперь используется только один маршрут с использованием атрибутаexact
, что гарантирует, что маршрут будет совпадать только с/home
. - Путь для пользователя (
/user
) оставлен без изменений.
Эти изменения помогут сделать код более чистым и понятным. Попробуйте использовать предложенный вариант.
Простое решение
Метод 1:
<Route exact path="/" component={Home}/>
Примечание:
<Route exact path="/" component={Home}/>
и <IndexRoute component={Home}/>
можно считать эквивалентными.
Метод 2:
npm install react-router@3 --save
Обнаружена ошибка: Невозможное нарушение: Неверный тип элемента: ожидался строковый тип (для встроенных компонентов) или класс/функция, но получен объект
React-router URLs не работают при обновлении страницы или ручном вводе адреса
Что делает npm install --legacy-peer-deps? Когда рекомендуется использовать и какой потенциальный случай?
React - Изменение неконтролируемого ввода
"Не используйте Route или withRouter() вне Router при работе с react-router 4 и styled-components в React"