Запрет React Router от прямого доступа к URL без навигации - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь создать небольшой игровой интерфейс, состоящий из разных страниц (меню «Пуск», экран загрузки и т. Д. c).
Конечно, я не хочу, чтобы пользователь мог перемещаться между этими страницами, просто изменив URL в адресной строке. Есть ли способ игнорировать / отклонять ввод пользователя из адресной строки и просто перемещаться по страницам из кода?

Большое спасибо заранее! :)

Ответы [ 3 ]

1 голос
/ 31 марта 2020

Мне удалось сделать это с помощью следующих шагов:

  • Создать контекст, в котором я храню lastVisitedLocation, это значение редактируется, когда пользователь нажимает на ссылку. (Мы можем обновить его из любого места в приложении!)
  • Контекст также предоставляет функцию registerLocation, которая изменяет предыдущее значение.
const LocationContext = React.createContext(null);

function LocationContextProvider({ children }) {
  const lastVisitedLocation = React.useRef(null);
  function registerLocation(location) {
    lastVisitedLocation.current = location;
  }
  return (
    <LocationContext.Provider value={{ registerLocation, lastVisitedLocation }}>
      {children}
    </LocationContext.Provider>
  );
}
  • Обертывание Link из react-router-dom и изменяйте lastVisitedLocation всякий раз, когда мы нажимаем на ссылку.
const MySpecialLink = React.forwardRef((props, ref) => {
  const { registerLocation } = React.useContext(LocationContext);
  return (
    <Link onClick={() => registerLocation(props.to)} ref={ref} {...props} />
  );
});

  • Создайте ловушку, которая проверяет, что пользователь ранее перемещался в приложении, и что мы не в разрешенном маршруте. Если мы обнаружим прямой доступ через URL, выведите ошибку (мы можем реализовать любое желаемое поведение).
const PUBLIC_ALLOWED_ROUTES = ["/home", "/"];

function useInvalidUrlAccess() {
  const currentLocation = useLocation();
  const { lastVisitedLocation } = React.useContext(LocationContext);
  if (
    lastVisitedLocation.current === null &&
    !PUBLIC_ALLOWED_ROUTES.includes(currentLocation.pathname)
  ) {
    throw new Error("Cannot come here directly, buddy");
  }
}
  • Оберните Switch в LocationContextProvider.
    <LocationContextProvider>
      <MySpecialLink to="/">Home</MySpecialLink>
      <br />
      <MySpecialLink to="/page1">Page 1</MySpecialLink>
      <br />
      <MySpecialLink to="/page2">Page 2</MySpecialLink>
      <br />
      <Switch>
        <Route exact path="/">
          <HomePage />
        </Route>
        <Route exact path="/home">
          <HomePage />
        </Route>
        <Route exact path="/page1">
          <Page1 />
        </Route>
        <Route exact path="/page2">
          <Page2 />
        </Route>
        <Route component={NotFound} />
      </Switch>
    </LocationContextProvider>
  • Защитите свои компоненты, вызвав зацепку на верхнем уровне функции

function HomePage() {
  useInvalidUrlRoutes();
  return "This is the content of HOME the page";
}
function Page1() {
  useInvalidUrlRoutes();
  return "This is the content of the page 1";
}
function Page2() {
  useInvalidUrlRoutes();
  return "This is the content of the page 2";
}
function NotFound() {
  return "You hit the wrong road, buddy!";
}

Наконец, вот рабочие коды и демонстрационная коробка . Я использовал throw new Error, например, чтобы пометить маршрут как не судоходный напрямую, но в основном вы можете делать все что угодно.

0 голосов
/ 31 марта 2020

Вы не можете запретить браузеру открывать введенный URL в строке URL.

Вы можете иметь флаг в состоянии приложения, который показывает, инициирован ли текущий сеанс с домашней страницы, и установить его на true только на компоненте домашней страницы. Затем вы можете добавить следующее условие к компонентам страницы, доступ к которым вы хотите ограничить: если флаг true, то страница может быть открыта, в противном случае сделайте перенаправление на домашнюю страницу.

Be помните, что из-за введенных ограничений невозможно перезагрузить страницы с ограниченным доступом.

PS: Это довольно запутанное требование, нарушающее работу Интернета. В чем причина?

0 голосов
/ 31 марта 2020

Вы можете перенаправить все URL на свою главную страницу.

import {
    Redirect
} from "react-router-dom";

     <Redirect from={`${match.url}/`} to={`${match.url}/mainpage`} />

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...