Search code examples
next.jsurl-routingreact-context

Next.js advanced client-side routing


In a Next.js app (full-featured, not next export) that uses React Context for state management and the file-system based router, how can you implement advanced routing?

I want to have preconditions for certain pages, so for instance if you try to load /foo but the Context doesn't have a given property set correctly, it'll route you to /bar.

The actual logic is complex and varies by page, so I'm looking for an approach that's easy to maintain.

Note that these preconditions are not authorization-related, so they do not need to be enforced server-side. It's more like "you need to fill out this form before you can go here."

The use of Context imposes some constraints:

  • Context must be accessed in a React component or in a custom Hook
  • Using a custom server for routing is not an option, as that would lose the Context - it has to use client-side routing
  • The current Context has to be checked (I tried decorating useRouter, but if the Context was changed right before router.push, the custom Hook saw the old values)

Update: It's also good to avoid a flash when the page loads before rerouting happens, so a side goal is to return a loading indicator component in that case.


Solution

  • I believe you can create a HOC and wrapped every pages with you HOC that takes arguments e.g. { redirects: '/foo' }

    // pages/bar.tsx
    const Page = () => {...}
    
    export default RouteHOC({ redirects: '/foo' })(Page)
    

    the HOC file will be something like this

    // 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
    }
    

    This is pretty okay to be maintainable I think. You just create all the logic in HOC and when you want to update the logic - you just have to edit it in 1 file.

    Well this is one option I can think of when reading your question - sorry if I misunderstood it in any way. There will always be a better way out there as we all know we can improve and adapt to new situation every seconds :D. Cheers 🥂!!