#reactjs
#reactjs
Вопрос:
Я новичок в react. В моем приложении есть множество ресторанов с разными категориями. Пользователь должен иметь возможность перейти на страницу, которая загружает все рестораны по категориям, или иметь возможность перейти на страницу ресторана.
Path / eat-out загружает все доступные категории с несколькими предложениями для ресторанов.
Страница категории работает нормально, но когда я пытаюсь войти на страницу ресторана, она по-прежнему загружает компонент категории вместо ресторана.
Мне нужно иметь путь к ресторанам / категориям или ресторанам / ресторанам, где каждый из них загружал бы другой компонент.
return (
<content className="content">
<Switch>
<Route exact path="/" render={() => <Dashboard />} />
<Route exact path="/reservations" render={() => <Reservations />} />
<Route exact path="/eat-out" render={() => <EatOut />} />
<Route
exact
path="/eat-out/:category"
render={() => <CategoryRestaurants />}
/>
<Route
exact
path="/eat-out/:restaurant"
render={() => <RestaurantPage />}
/>
</Switch>
</content>
);
};
Возможно ли выполнить такую маршрутизацию?
Комментарии:
1. Как бы вы определили разницу между a
category
и arestaurant
?
Ответ №1:
Это возможно, если вы знаете, что такое категории и / или рестораны, но, вероятно, не то, что вы действительно хотите:
import React from "react";
import { Route, BrowserRouter as Router, Switch } from "react-router-dom";
import "./styles.css";
const CategoryRestaurants = ({ category }) => <div>Category: {category}</div>;
const RestaurantPage = ({ restaurant }) => <div>Restaurant: {restaurant}</div>;
const KNOWN_CATEGORIES = ["cat1", "cat2", "cat3"];
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Router>
<Switch>
<Route
exact
path="/eat-out/:category"
render={(props) => {
// Use the list of known categories to decide where to go
const param = props.match.params.category;
return KNOWN_CATEGORIES.includes(param) ? (
<CategoryRestaurants category={param} />
) : (
<RestaurantPage restaurant={param} />
);
}}
/>
</Switch>
</Router>
</div>
);
}
Вероятно, было бы лучше иметь более определенные URL-адреса, такие как /eat-out/category/:category
и /eat-out/restaurant/:restaurant
.
Комментарии:
1. Кроме того, вы можете попробовать загрузить данные категории / ресторана, и если они не найдены, они передают другие данные. Если вы это сделали, вероятно, создайте компонент для обработки этого и предоставьте уведомление о загрузке. В качестве альтернативы вы можете получить данные, которые содержат оба элемента, и каждый элемент указывает его тип, а затем выбрать компонент на основе типа данных.
Ответ №2:
Здесь есть несколько подходов, которые могут вам подойти.
Сопоставление шаблонов
Если значения для category
и restaurant
имеют разные шаблоны, которые вы можете проверить с помощью регулярных выражений, вы можете использовать сопоставление шаблонов для ваших параметров URL, например:
path="/eat-out/:category([A-Za-z] )"
path="/eat-out/:restaurant([0-9] )"
Сопоставление статических значений
Или, если вы category
заранее знаете все значения restaurant
(т. Е. Значения являются статическими и не извлекаются из сервера / базы данных), вы можете создать подобный список и использовать регулярное выражение:
const categories = ["Pizza", "Hamburgers", "Vegan"];
const categoryPattern = categories.join("|");
const restaurants = ["Tom's Sandwiches", "Super Restaurant Co."];
const restaurantPattern = restaurants.join("|");
path={`/eat-out/:category(${categoryPattern})`}
path={`/eat-out/:restaurant(${restaurantPattern})`}
Измените пути
Если значения не могут быть разделены по шаблону, и вы не знаете значения заранее, и вы не возражаете немного изменить пути, вы можете добавить путь перед параметром URL, чтобы указать разницу, например:
path="/eat-out/categories/:category"
path="/eat-out/restaurants/:restaurant"
Внутренняя логика компонентов
В противном случае вы можете создать отдельный компонент, который использует более сложную логику для определения внутренней разницы между категорией и рестораном, а затем возвращает либо <CategoryRestaurants>
или <RestaurantPage>
, в зависимости от того, что является релевантным.
Например, вы можете попробовать извлечь данные категории на основе имени / идентификатора, и если это не удастся, то вместо этого извлеките данные ресторана. В качестве альтернативы, вы можете создать один маршрут в своем API, который принимает имя / идентификатор и возвращает правильный объект, затем просто выясните, какой тип объекта вы получили во внешнем интерфейсе, и отобразите соответствующим образом.
Таким образом, у вас было бы что-то вроде этого:
<Route
path="/eat-out/:categoryOrRestaurant"
render={() => <CategoryOrRestaurantPage/>}
/>