简体   繁体   中英

Is it possible to define hash route in next.js?

I had already made a modal component with <HashRouter> in react-router that became active and inactive with hash url ie modals is inactive when url is /route and modal1 is active when url is /route#modal1 . There is any ways to define hash routes in next.js?

The part of the url starting with the hash symbol (that identifies an html entity) is never sent to the server, so you cant match the url serverside (if the browser loads /route#modal1 the server will load /route ) what you can do is :

Option 1 Handle the modal rendering client side, using next/router in your component with something like this :
(im assuming you are using class components)

  import Router from 'next/router'

  ....

  componentDidMount(){
    let id = Router.asPath.match(/#([a-z0-9]+)/gi )
    if(id){
      // i will show the modal
    }else{
      // something else
    }
  }

Option 2 Pass the id to the url without # .
In your server.js add a route similar to this :

  server.get('/route/:id?', (req, res) => {
    let {id} =  req.params 
    return app.render(req, res, '/mypage', { id})
  })

And then grab the id, ex. in getInitialProps

  static async getInitialProps (context) {
    let ctx  = context.query;
    return ctx
  }

And handle the modal

  componentDidMount(){
    let {id} =  this.props    
    if(id){
      // i will show the modal
    }else{
      // something else
    }
  }

You can add a hash using the next/router.

Some pages I change the component that renders based on a state string, so to make sure I know which route I'm on (and keep the back button working) I add a state string stage as a hash to the URL when it detects a change.

React.useEffect(() => {
  router.push(`/booking#${stage}`)
}, [stage])

This will only work client side though.

You can use next/router to accomplish that.

In our case we use hash routing on a specific page to render different components depending on the hash url, so the user can go back and forth using regular web navigations buttons

// page.js

export default function MyPage() {
  const router = useRouter();
  const hash = router.asPath.split('#')[1] || '';
  const showModal = hash === 'modal1' ? true : false;
  const openModal = () => {
    router.push({ hash: 'modal1' });
  }  
  return (
    <>
      <h1>MyPage</h1>
      <Button onClick={openModal}>Open Modal 🙂</Button>
      {showModal && <ModalOne />}
    </>
  )
}
// ModalOne.js

export default function ModelOne {
  const router = useRouter();
  const closeModal = () => {
    router.push({ hash: '' });
  }
  return (
    <>
        <h1>Hello Modal</h1>
        <Button onClick={closeModal}>Close Modal 🙃</Button>
    </>
  )
}

Every time the router hash changes a re render is triggered, opening the modal in a similar way to what you would expect on a SPA

This also has the added benefit of closing the modal when pressing back on a mobile device, as it was in our use case expectations.

Note: I'm using nextjs version 12.1.0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM