Handle Communication Between Component in layout.tsx (Nav Bar) and Other Pages
Answered
Tan posted this in #help-forum
TanOP
I have a bottom Navigation Bar and I can go BACK and NEXT. When I click NEXT I basically use the router to go to the next path, for example page-1 to page-2. The Navigation Bar is just responsible for changing pages and so I placed it inside the layout.tsx so it stays across all pages...
How can I validate the data of the user If I go from page-1 to page-2. I'm new to NextJS but I feel stuck...
It would be nice to have a validate function fire on each page when I click next, but I have no idea how to achieve this... And ChatGPT is not helping 🥲
How can I validate the data of the user If I go from page-1 to page-2. I'm new to NextJS but I feel stuck...
It would be nice to have a validate function fire on each page when I click next, but I have no idea how to achieve this... And ChatGPT is not helping 🥲
Answered by Tan
I finally made it! I used:
- useContext: to get the navigationBar component and be able to invoke functions like next or back
- eventEmitter: to listen for next and back events from nevigation bar.
On every page now I listen for next events, I validate the data (in this case a simple checkbox) and then move to the next step... It works for me, I hope It's the right approach!
- useContext: to get the navigationBar component and be able to invoke functions like next or back
- eventEmitter: to listen for next and back events from nevigation bar.
On every page now I listen for next events, I validate the data (in this case a simple checkbox) and then move to the next step... It works for me, I hope It's the right approach!
11 Replies
TanOP
This is the thing I want to achieve
@Tan I have a bottom Navigation Bar and I can go BACK and NEXT. When I click NEXT I basically use the router to go to the next path, for example page-1 to page-2. The Navigation Bar is just responsible for changing pages and so I placed it inside the layout.tsx so it stays across all pages...
How can I validate the data of the user If I go from page-1 to page-2. I'm new to NextJS but I feel stuck...
It would be nice to have a validate function fire on each page when I click next, but I have no idea how to achieve this... And ChatGPT is not helping 🥲
Silver Fox
1 - You can send data in query of the router.
2 - You can post the data to the server and fetch it on the other side (best method)
3 - You can send data in the route.
2 - You can post the data to the server and fetch it on the other side (best method)
3 - You can send data in the route.
TanOP
Thanks for the reply but maybe I didn't explain it well:
1 - The user is on /page1
2 - The user didn't check the terms on /page1
3 - When the user clicks NEXT I have to somehow check that the terms on /page1 is checked before moving to /page2
4 - Of course if the user clicks on NEXT and didn't checked the box it will show an error message and it will not go to /page2
5 - How can I check this? The bottom nav bar (BACK - NEXT) is on layout component and is rendered on top of every page and /page1 - /page2 are 2 different routes
I hope this is clear or maybe I didn't understand.
1 - The user is on /page1
2 - The user didn't check the terms on /page1
3 - When the user clicks NEXT I have to somehow check that the terms on /page1 is checked before moving to /page2
4 - Of course if the user clicks on NEXT and didn't checked the box it will show an error message and it will not go to /page2
5 - How can I check this? The bottom nav bar (BACK - NEXT) is on layout component and is rendered on top of every page and /page1 - /page2 are 2 different routes
I hope this is clear or maybe I didn't understand.
@Tan Thanks for the reply but maybe I didn't explain it well:
1 - The user is on /page1
2 - The user didn't check the terms on /page1
3 - When the user clicks NEXT I have to somehow check that the terms on /page1 is checked before moving to /page2
4 - Of course if the user clicks on NEXT and didn't checked the box it will show an error message and it will not go to /page2
5 - How can I check this? The bottom nav bar (BACK - NEXT) is on layout component and is rendered on top of every page and /page1 - /page2 are 2 different routes
I hope this is clear or maybe I didn't understand.
Silver Fox
assume you have a
when the user clicked on the next button, you can do
did I understand you correctly?
input type="checkbox", thenconst [checked, setChecked] = useState(false)
const onChange = () => setChecked(!checked)
return (<input type="checkbox" onChange={onChange}/>)when the user clicked on the next button, you can do
const onClick = () => checked ? router.push("/page-2") : setError("Agree to the terms before moving ahead!")did I understand you correctly?
TanOP
Yess this is pretty much what I want to do. But how do I get the onClick event since the NavigationBar is not in /page1 but is on layout.tsx?
@Tan Yess this is pretty much what I want to do. But how do I get the onClick event since the NavigationBar is not in /page1 but is on layout.tsx?
Silver Fox
you are simply use the selectors or refs.
TanOP
This is my navigation-bar.tsx it's only responsible for going back and next using an array:
'use client'
import React, { useEffect, useState } from 'react'
import { logger } from '@/utils/logger'
import { usePathname, useRouter } from 'next/navigation'
type NavLink = {
path: string
replace: boolean
}
const navLinks: NavLink[] = [
{ path: '/test-navigation/page-1', replace: false },
{ path: '/test-navigation/page-2', replace: false },
]
const NavigationBar = () => {
const router = useRouter()
const pathname = usePathname()
const getNavLinkIndex = () => {
return navLinks.findIndex((x) => x.path === pathname)
}
const [index, setIndex] = useState<number>(getNavLinkIndex())
const updatePathIndex = () => {
const pathIndex = getNavLinkIndex()
setIndex(pathIndex)
logger.log('NavigationBar :: updatePathIndex :: ' + pathIndex)
}
const switchPage = (idx: number) => {
if (idx > navLinks.length - 1) {
logger.warn(
'NavigationBar :: Index is greater than current navigation length'
)
return
}
if (idx < 0) {
logger.warn('NavigationBar :: Index is less than zero')
return
}
setIndex(idx)
const navLink = navLinks[idx]?.path
router.push(navLink)
logger.log('NavigationBar :: switchPage :: ' + navLink)
}
const next = () => {
const nxt = index + 1
logger.log('NavigationBar :: next :: ' + nxt)
switchPage(nxt)
}
const back = () => {
const nxt = index - 1
logger.log('NavigationBar :: back :: ' + nxt)
switchPage(nxt)
}
useEffect(updatePathIndex, [pathname])
return (
<div className="flex justify-between bg-green-300 p-6 ">
<button onClick={back}>BACK</button>
<button onClick={next}>NEXT</button>
</div>
)
}
export default NavigationBarIs mounted on the root layout:
You say on page1 I can get the Next button (using the id for example) and subscribe onClick event right?
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={`${inter.className} h-screen-svh flex flex-col`}>
<Providers>
<div className="flex-1">{children}</div>
<NavigationBar />
</Providers>
</body>
</html>
)
}You say on page1 I can get the Next button (using the id for example) and subscribe onClick event right?
Silver Fox
yes
TanOP
I finally made it! I used:
- useContext: to get the navigationBar component and be able to invoke functions like next or back
- eventEmitter: to listen for next and back events from nevigation bar.
On every page now I listen for next events, I validate the data (in this case a simple checkbox) and then move to the next step... It works for me, I hope It's the right approach!
- useContext: to get the navigationBar component and be able to invoke functions like next or back
- eventEmitter: to listen for next and back events from nevigation bar.
On every page now I listen for next events, I validate the data (in this case a simple checkbox) and then move to the next step... It works for me, I hope It's the right approach!
Answer
TanOP