I had already made a modal component with <HashRouter>
in react-router
that became active and inactive with hash url i.e 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 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
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.
© 2022 - 2024 — McMap. All rights reserved.