【问题标题】:Next.js advanced client-side routingNext.js 高级客户端路由
【发布时间】:2021-10-06 06:51:50
【问题描述】:

在使用 React Context 进行状态管理和基于文件系统的路由器的 Next.js 应用程序(全功能,not next export)中,您如何实现高级路由?

我想为某些页面设置先决条件,例如,如果您尝试加载 /foo 但上下文没有正确设置给定属性,它会将您路由到 /bar

实际逻辑很复杂,因页面而异,所以我正在寻找一种易于维护的方法。

请注意,这些先决条件授权无关,因此不需要在服务器端强制执行。这更像是“您需要先填写此表格才能到这里。”

上下文的使用施加了一些限制:

  • 必须在 React 组件或自定义 Hook 中访问上下文
  • 不能使用自定义服务器进行路由,因为这会丢失上下文 - 它必须使用客户端路由
  • 必须检查当前上下文(我尝试装饰useRouter,但如果在router.push之前更改了上下文,自定义Hook会看到旧值)

更新:在重新路由发生之前页面加载时避免闪烁也很好,因此在这种情况下,一个附加目标是返回一个加载指示器组件。

【问题讨论】:

  • 这听起来像是标准的动态路由,甚至可能捕获所有路由都应该工作。你累了吗?它们都可以在客户端完成,并且都可以访问您的上下文。当您构建您的站点时,您甚至可以在 staticProps 中预先执行逻辑,并在使用 ISR 更新逻辑时进行更新,或者只检查每个请求。你有几个选择。 nextjs.org/docs/routing/dynamic-routes
  • @SeanW 我们已经在做动态路由和捕获所有路由。将此更多地视为基于客户端状态(通常适用于多个页面)的页面前提条件,而不是典型的路由问题。
  • 使用Router HOC 包裹在 Next.js 中的自定义 HOC 可能是最简单的解决方案 - nextjs.org/docs/api-reference/next/router#withrouter

标签: next.js url-routing react-context


【解决方案1】:

我相信你可以创建一个 HOC 并用你的 HOC 包装每个页面,例如{ 重定向:'/foo' }

// pages/bar.tsx
const Page = () => {...}

export default RouteHOC({ redirects: '/foo' })(Page)

HOC 文件会是这样的

// hoc/RouteHOC.tsx
const RouteHOC = ({ redirects }) => (WrappedComponent) => {
  
  // you can do your logic here with the context.. even filling up a form here 
  // too also can.. (like returning a modal first before the real Component). 
  // useEffect work here too..
  
  const { replace } = useRouter()
  
  // then after you want to replace the url with other page
  replace(redirects)
  
  return WrappedComponent
}

我认为这很好维护。您只需在 HOC 中创建所有逻辑,当您想要更新逻辑时 - 您只需在 1 个文件中对其进行编辑。

嗯,这是我在阅读您的问题时能想到的一种选择 - 如果我以任何方式误解了它,请见谅。总会有更好的出路,因为我们都知道我们可以每秒钟改进和适应新情况:D。干杯?!!

【讨论】:

  • 这似乎基于一些原型设计。
【解决方案2】:

你可以这样做。

const Component = () => {
  const example = useExample()

  return <div id='routes'>
    <a href='/example1'>Example 1</a>
    {example.whatever && <a href='/example2'>Example 1</a>}
  </div>
}

【讨论】:

  • 很高兴知道,但在服务器端我无法访问上下文,所以我无法检查上下文相关的先决条件。
  • 我不确定语句的哪一部分不正确。您无法访问 Context 服务器端。我需要查询上下文才能正确路由。因此,我需要在客户端做路由。
  • 不幸的是,我尝试了类似的技术,将装饰器添加到useRouter。当setSomeContextrouter.push 之前执行时,上下文更新似乎发生在推送功能运行之后(显然更新是异步的)。因此,检查将在第一次尝试时失败,但在第二次尝试时成功。
猜你喜欢
  • 2021-08-27
  • 1970-01-01
  • 2023-02-13
  • 2014-09-05
  • 1970-01-01
  • 2020-02-05
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多