首页 > 解决方案 > Prevent React Router from accessing directly an URL without navigating

问题描述

I am trying to create a small game interface that consists of different pages (start menu, loading screen, etc).
Of course I don't want the user to be able to navigate between those pages just by changing the URL in the address bar. Is there a way to ignore / reject user input from the address bar and just navigate the pages from within the code?

Thank you very much in advance! :)

标签: javascriptreactjsreact-router

解决方案


我可以通过以下步骤做到这一点:

  • 创建一个我存储的上下文,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>
  );
}
  • 每当我们点击一​​个链接时,包装Linkreact-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");
  }
}
  • 把你包SwitchLocationContextProvider.
    <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例如直接将路线标记为不可导航,但基本上你可以做任何事情。


推荐阅读