How to Handle Promises in a Provider Component in Next.js 14 Layout?
I’m trying to use LucidProvider
in my Next.js 14 layout to wrap all my components. Inside the provider, I initialize Lucid
and update the state. However, Lucid
returns a promise, which is causing the following error:
Error: Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.
Here’s the initialization logic in LucidProvider.tsx
:
const blockfrost = new Blockfrost(BF_URL, BF_PID);
Lucid(blockfrost, NETWORK).then(setLucid).catch((error) => console.log(error));
When I comment out these lines, the error disappears. I’ve tried different approaches, including using default and named imports, as well as dynamic
, but none of them resolved the issue. How can I properly pass the resolved promise as a provider in the Next.js 14 layout?
LucidProvider.tsx
'use client';
import React, { createContext, useContext, useEffect, useState } from "react";
import { Blockfrost, Lucid, LucidEvolution, Network } from "@lucid-evolution/lucid";
interface LucidContextType {
lucid: LucidEvolution | undefined;
}
const LucidContext = createContext<LucidContextType | undefined>(undefined);
const BF_URL = process.env.NEXT_PUBLIC_BF_URL!;
const BF_PID = process.env.NEXT_PUBLIC_BF_PID!;
const NETWORK = process.env.NEXT_PUBLIC_CARDANO_NETWORK as Network;
export interface ProvidersProps {
children: React.ReactNode;
}
export default function LucidProvider({ children }: ProvidersProps) {
const [lucid, setLucid] = useState<LucidEvolution>();
useEffect(() => {
const blockfrost = new Blockfrost(BF_URL, BF_PID);
Lucid(blockfrost, NETWORK).then(setLucid).catch((error) => console.log(error));
}, []);
return (
<LucidContext.Provider value={{ lucid, }}>
{children}
</LucidContext.Provider>
);
};
export const useLucid = () => {
const context = useContext(LucidContext);
if (!context) throw new Error("useLucid must be used within a LucidProvider");
return context;
};
Layout.tsx
import dynamic from "next/dynamic";
// const LucidProvider = dynamic(() => import('./LucidProvider'))
import LucidProvider from "./LucidProvider";
..
..
..
..
..
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html suppressHydrationWarning lang="en">
<head />
<body className={clsx(
"min-h-screen bg-background font-sans antialiased",
fontSans.variable,
fontComfortaa.variable
)}>
<LucidProvider>
<Navbar />
<Providers themeProps={{ attribute: "class", defaultTheme: "dark" }}>
<div className="relative flex flex-col h-screen">
<main className="container mx-auto flex-grow">{children}</main>
</div>
</Providers>
</LucidProvider>
</body>
</html>
);
}