2

I recently migrated React application to nextjs.

There we exchanged the HashRouter with the nextjs Router.

When someone deep links to our page I want that the Urls are forwarded to the routes without the #.

Example: Forward /#/contact to /contact

Redirecting within next.config.js

First I tried the following within next.config.js:

module.exports = {
  async redirects() {
    return [
      {
        source: '/#/:slug*',
        destination: '/:slug*',
        permanent: true
      }
    ]
  }
}

--> But this does not work as the next router ignores the # part of the url.

Redirect within _app.tsx

Then I wrote an custom hook useHashRouterRedirects.ts.

import { useEffect } from 'react'
import { useRouter } from 'next/router'

/**
 * Redirecting the old routes # router URLs to the new nextjs urls.
 * (This does not work within the next.config.js)
 */
export const useHashRouterRedirects = () => {
  const { push } = useRouter()

  useEffect(() => {
    const hashRoute = window.location.hash
    if (hashRoute.includes('#')) {
      const routeWithoutHash = hashRoute.replace('#', '')
      push(routeWithoutHash)
    }
  }, [])
}

and then import it within _app.tsx

useHashRouterRedirects()

--> But this loads first the old page and then the new page. It should forward the URLs quicker.

What's better?

Is there any other option on how I can redirect the # routes?

basti500
  • 600
  • 4
  • 20
  • 1
    The hash (`#`) portion of the URL is not sent to the server - see https://stackoverflow.com/questions/3664257/why-is-the-hash-part-of-the-url-not-available-on-the-server-side. You have to handle it on the client-side. – juliomalves May 20 '22 at 23:02

1 Answers1

3

Hash routes can only be handled on the client side.

The following solution immediately redirects and does not load the previous page first.

Add a new file inside the public folder.

public/hash-router-redirect.js

if (window.location.hash.includes('#')) {
    const routeWithoutHash = window.location.hash.replace('#', '')
    window.location.replace(routeWithoutHash)
}

Inside your pages folder navigate to or create) _document.js

webview/src/pages/_document.tsx

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head>
        ...
        <script async type='text/javascript' src='/hash-router-redirect.js'></script>
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

basti500
  • 600
  • 4
  • 20