Next.js Discord

Discord Forum

context from context provider in layout not available in page?

Unanswered
Giant Chinchilla posted this in #help-forum
Open in Discord
Giant ChinchillaOP
I am getting error "Error: (0 , _components_Context_LangContext_LangContextWEBPACK_IMPORTED_MODULE_2.useLangContext) is not a function"

src/app/[lang]/page.tsx:
const {dictionary} = useLangContext();

Is it because both layout and page are server components?

Code below:

11 Replies

Giant ChinchillaOP
// LangContext.tsx
"use client";

import React, { useContext } from "react";
import { Locale } from "@root/i18n-config";
import { Dictionary } from "@/types/types";

interface ILangContext {
    lang: Locale;
    dictionary: Dictionary;
};

export const LangContext = React.createContext<ILangContext | undefined>(undefined);

interface ILangProvider {
    lang: Locale;
    dictionary: Dictionary;
    children?: React.ReactNode;
};

export const LangProvider: React.FC<ILangProvider> = (props) => {
    return (
        <LangContext.Provider value={{
            lang: props.lang,
            dictionary: props.dictionary,
        }}>{props.children}</LangContext.Provider>
    );
};

export const useLangContext = () => {
    const context = useContext(LangContext);

    if (context === undefined) {
        throw new Error("useLangContext must be used within a LangProvider");
    }

    return context;
};
// layout.tsx

import type { Metadata } from "next";
import NextTopLoader from "nextjs-toploader";
import BaseLayout from "@/layouts/BaseLayout/BaseLayout";
import { getDictionary } from "@/get-dictionary";
import { Locale } from "@root/i18n-config";
import { Inter } from "next/font/google";
import "./globals.scss";
import "bootstrap/dist/css/bootstrap.min.css";
import { LangProvider } from "@/components/Context/LangContext/LangContext";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Home",
};

export default async function RootLayout({
    params: { lang },
    children,
}: Readonly<{
    params: { lang: Locale };
    children: React.ReactNode;
}>) {
    const dictionary = await getDictionary(lang);

    return (
        <html lang={lang}>
            <body className={inter.className}>
                <LangProvider lang={lang} dictionary={dictionary}>
                    <BaseLayout>
                        {children}
                    </BaseLayout>
                </LangProvider>
            </body>
        </html>
    );
};
// src/app/[lang]/page.tsx

import { Locale } from "@root/i18n-config";
import Link from 'next/link';
import { useLangContext } from "@/components/Context/LangContext/LangContext";

export default function IndexPage() {
    const {dictionary} = useLangContext(); // ERROR HERE

    return (
        <div></div>
    );
};
the same const {dictionary} = useLangContext(); does work in a client component that is inside <BaseLayout>
Giant ChinchillaOP
or does layout not wrap pages?
I have no idea why the context is not available in page, but is available in BaseLayout
Giant ChinchillaOP
do I also need to do const dictionary = await getDictionary(lang); in page.tsx instead of using the context?
because that works
but that kind of defeats the purpose of layout
because i am repeating myself twice
Sun bear
Is the page.tsx a client component? It should be the case if you use "use..." Hooms