Разные маршрутизаторы, разные компоненты, один и тот же путь

#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 и a restaurant ?

Ответ №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/>}
/>