Skip to content

Instantly share code, notes, and snippets.

@artursopelnik
Created October 26, 2025 13:44
Show Gist options
  • Save artursopelnik/edd4fc74176015039963a4524aa21a97 to your computer and use it in GitHub Desktop.
Save artursopelnik/edd4fc74176015039963a4524aa21a97 to your computer and use it in GitHub Desktop.
DataProvider
"use client";
import { createContext, useContext, ReactNode } from "react";
import { wrapPromise } from "@/lib/wrapPromise";
import { fetchInfo } from "@/services/infoService";
import { fetchAttachment } from "@/services/attachmentService";
type DataContextType = {
data: { info: any; attachment: any };
};
const DataContext = createContext<DataContextType | undefined>(undefined);
export function useData() {
const context = useContext(DataContext);
if (!context) throw new Error("useData must be used within DataProvider");
return context;
}
// Suspense-kompatible Promise
const resource = wrapPromise(
(async () => {
const [info, attachment] = await Promise.all([fetchInfo(), fetchAttachment()]);
return { info, attachment };
})()
);
export function DataProvider({ children }: { children: ReactNode }) {
const data = resource.read();
return <DataContext.Provider value={{ data }}>{children}</DataContext.Provider>;
}
@artursopelnik
Copy link
Author

// lib/wrapPromise.ts
export function wrapPromise(promise: Promise) {
let status = "pending";
let result: T;
const suspender = promise.then(
(r) => {
status = "success";
result = r;
},
(e) => {
status = "error";
result = e;
}
);

return {
read() {
if (status === "pending") throw suspender;
if (status === "error") throw result;
return result;
},
};
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment