Today we are going to learn a way to create a Head component that repeats on our pages and serves to customize each page we visit, so that it is built on a Server Side Render (SSR).
The first thing we are going to do is create an object with the attributes that we are going to pass to our Head:
export interface HeadObj { title: string; description: string; keywords: string; }
The code is in TypeScript, if you need to pass it to JavaScript you must remove the types.
Now we have to create a component that will have our Head, we will call it Head.tsx including the following:
import { HeadObj } from '@/objects/Page'; import Head from 'next/head'; import React from 'react'; interface Props { headerObj?: HeadObj; } function HeadComponent({ headerObj } : Props) { return ( <Head> {/* Common Meta */} <title>{headerObj?.title}</title> <meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" /> <meta content="IE=edge" httpEquiv="X-UA-Compatible" /> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" /> <meta name="description" content={headerObj?.description} /> <meta name="keywords" content={headerObj?.keywords} /> </Head> ); } export default HeadComponent;
It is a very simple Head, but we can put all the properties we need.
Now, to make it work cleanly and on all pages, we are going to include it using a context through a Service Provider.
I have called it UtilsContext.tsx
// context/ServiceContext.tsx import HeadComponent from '@/components/Head'; import React, { createContext, useContext } from 'react'; // Create context const UtilsContext = createContext<{ } undefined>(undefined); export const UtilsProvider: React.FC<{ children: React.ReactNode, headerObj: any }> = ({ children, headerObj }) => { return ( <UtilsContext.Provider value={ { }}> <HeadComponent headerObj={headerObj} /> {children} </UtilsContext.Provider> ); };
Now we import the context or service provider, for this we have to go to the file or create it inside pages, called _app.tsx add the following code:
// pages/_app.tsx import React from 'react'; import { AppProps } from 'next/app'; import { UtilsProvider } from '@/context/UtilsContext'; const MyApp: React.FC = ({ Component, pageProps }) => { const { headerObj, ...rest } = pageProps; return ( <UtilsProvider headerObj={headerObj}> <Component {...rest} /> </UtilsProvider> ); }; export default MyApp;
And now it is ready to be used in any of our pages.
For example in index.tsx
// src/app/page.tsx import React, { use, useEffect } from 'react'; import { HeadObj } from '@/objects/Page'; const Home: React.FC = ({ }) => { return ( <div> <h1>My main page</h1> </div> ); }; export default Home; export async function getServerSideProps() { // Create header object const headerObj: HeadObj = { title: "My main page, changed title", description: "description", keywords: "indexKeywords", }; return { props: { headerObj: headerObj, // Pass the header object }, }; }
And with this it will fill in the title and SEO attributes of our page.
I have put it in getServerSideProps so that it does it at runtime, but I can put it in getStaticProps so that it gets it statically.