Is there an official example with live demo about how to use template.tsx and key?
Answered
Tomistoma posted this in #help-forum
TomistomaOP
I'd like to use the key prop showed at https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#templates
Is there any real example of how to use it?
Thanks!
Is there any real example of how to use it?
Thanks!
Answered by Eric Burel
and try "useParams" https://nextjs.org/docs/app/api-reference/functions/use-params
48 Replies
This seems extremely new
but to answer your question key is just a React key
this is how you control a component remount, a component whose key change will remount
so using the routeParam as key will force the template to remount on route params change
I think the idea is to get closer to what a "layout" means in React, while Next.js layouts are something much more static than we are used to
I can't find them in the changelog
@Eric Burel I can't find them in the changelog
TomistomaOP
"I can't find them in the changelog", does that mean it's not possible to use yet?
@Eric Burel this is how you control a component remount, a component whose key change will remount
TomistomaOP
It makes sense, thanks for the explanation!
@Eric Burel but to answer your question key is just a React key
TomistomaOP
Like that?
import { ReactNode } from 'react'
interface TemplateProps {
key: string
children: ReactNode
}
export default function Template({ key, children }: TemplateProps) {
return (
<div>
<h1>{key}</h1>
{children}
</div>
)
}@Tomistoma "I can't find them in the changelog", does that mean it's not possible to use yet?
will ask on general it's the first time I see them
but it's really really good news for the app route
the thing shown in the doc is internal to Next I think
it's just an example
I mean not an example but an illustration showing that Layout is rendered before Template
it's not what should get in your code
export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
is all you need
return <div>{children}</div>
}
is all you need
you don't have control over the "key" and should not care about it
@Eric Burel you don't have control over the "key" and should not care about it
TomistomaOP
Oh, I see. Actually, I wanted to use it. My pages always have a similar structure at the top of the page and an image is part of that, but not the same image, one for each page. So, I'd like to put that on layout.tsx there, but I can't, since there I don't know which page it is to select the correct image. So, I wanted to use the template with the key property for this reason.
I don't want to use metadata, because it would transform all my pages into dynamic
I guess I'll just have to create a component and put it on all pages instead of puting this component in the layout/template file as I wanted.
@Eric Burel will ask on general it's the first time I see them
TomistomaOP
Ok, thank you!
@Tomistoma Oh, I see. Actually, I wanted to use it. My pages always have a similar structure at the top of the page and an image is part of that, but not the same image, one for each page. So, I'd like to put that on layout.tsx there, but I can't, since there I don't know which page it is to select the correct image. So, I wanted to use the template with the key property for this reason.
Then I think a template will be ok it will just remount + rerender on route change
@Eric Burel Then I think a template will be ok it will just remount + rerender on route change
TomistomaOP
It won't be ok if I can't know which page is in template.tsx
So that I can select the proper image
Maybe try to see if you have a "params" prop in it with the current route params?
same for searchParams
basically log the props to see if you have what you want already, otherwise you can probably make it a client component and use the hook that give you the current route params
@Eric Burel Maybe try to see if you have a "params" prop in it with the current route params?
TomistomaOP
export default function Template(props) {
console.log(props)
return (
<div>
<h1>{props}</h1>
</div>
)
}{
children: {
'$$typeof': Symbol(react.element),
type: [Function (anonymous)],
key: null,
ref: null,
props: {},
_owner: null,
_store: {}
}
}It only has children. It doesn't have params or searchParams
ok so then you can make it a client component with "use client"
and try "useParams" https://nextjs.org/docs/app/api-reference/functions/use-params
Answer
@Eric Burel ok so then you can make it a client component with "use client"
TomistomaOP
I thought template just like layout couldn't be a client component. Let me try this. But one question, does this transform all my website into dynamic or something like that?
TomistomaOP
It doesn't work with fixed (like /about/page.tsx) routes, only routes like [slug]/page.tsx
I'll think if this makes sense in my application or not, thanks for replying!
You're welcome, you can use usePathname to get the whole path
and no this won't make the website dynamic, "client component" name is misleading: they can still be prerendered server-side
what it will change is that some JavaScript is needed to get the current path, so this part will need some hydration work on the frontend to become interactive again
if it's not really interactive, then having to use a client component is very slightly suboptimal, but not in any noticeable way
the site will even work without JS enabled
TomistomaOP
I see, thanks a lot for the explanation!!
@Eric Burel You're welcome, you can use usePathname to get the whole path
TomistomaOP
I'm sorry for this another question, but I've just had an idea: could I use __filename in layout.tsx or is there a problem using it?
I've tested it with npm run dev and it printed /repo/.next/server/app/about/page.js I could check what's after /app/ and use that to pick an image in layout.tsx?
TomistomaOP
'use client'
import Image from 'next/image'
import { usePathname } from 'next/navigation'
export default function MainImage() {
const pathName = usePathname()
const firstSlug = pathName.split('/')[0]
let imgSrc = 'home.png'
if (firstSlug === 'about') imgSrc = 'about.jpg'
return <Image alt="" src={/imgs/${imgSrc}} fill />
}I think I'll do something like that and import that on the layout.tsx, I think this should work well. Thank you!
@Tomistoma I'm sorry for this another question, but I've just had an idea: could I use __filename in layout.tsx or is there a problem using it?
might have surprsing behaviours on some host maybe vercel
@Eric Burel might have surprsing behaviours on some host maybe vercel
TomistomaOP
I see, thank you!