Skip to content

Instantly share code, notes, and snippets.

@bilalbhojani24
Created May 15, 2025 19:42
Show Gist options
  • Save bilalbhojani24/036ca6b37d325b8594431168824e79e5 to your computer and use it in GitHub Desktop.
Save bilalbhojani24/036ca6b37d325b8594431168824e79e5 to your computer and use it in GitHub Desktop.
import { createRoot } from "react-dom/client";
import React, {
createContext,
useContext,
useEffect,
useState,
useRef,
} from "react";
const DocumentTitleContext = createContext({
registerTitle: () => {},
unregisterTitle: () => {},
});
/**
* DocumentTitleProvider tracks the deepest mounted title and sets document.title accordingly
*/
export function DocumentTitleProvider({ children }) {
const [titles, setTitles] = useState([]);
const registerTitle = (title, id) => {
setTitles((prev) => [...prev, { id, title }]);
};
console.log(titles);
const unregisterTitle = (id) => {
setTitles((prev) => prev.filter((t) => t.id !== id));
};
useEffect(() => {
if (titles.length > 0) {
const latestTitle = titles[0].title;
document.title = latestTitle;
}
}, [titles]);
return (
<DocumentTitleContext.Provider value={{ registerTitle, unregisterTitle }}>
{children}
</DocumentTitleContext.Provider>
);
}
/**
* DocumentTitle sets the document title while mounted, respecting nesting
*/
export function DocumentTitleWrapper({ documentTitle, element }) {
const { registerTitle, unregisterTitle } = useContext(DocumentTitleContext);
const idRef = useRef(Symbol()); // Unique and stable per instance
useEffect(() => {
registerTitle(documentTitle, idRef.current);
return () => {
unregisterTitle(idRef.current);
};
}, [documentTitle]);
return <>{element}</>;
}
const Child2 = () => {
return <h1>Child2</h1>;
};
const Child3 = () => {
return <h1>Child3</h1>;
};
const Child = () => {
return (
<h1>
Child
<DocumentTitleWrapper documentTitle="Child2" element={<Child2 />} />
<DocumentTitleWrapper documentTitle="Child3" element={<Child3 />} />
</h1>
);
};
const Parent = () => {
return (
<h1>
parent
<DocumentTitleWrapper documentTitle="Child" element={<Child />} />
</h1>
);
};
export default function App() {
useEffect(() => {
console.log("App");
}, []);
return (
<DocumentTitleProvider>
<div className="App">
<DocumentTitleWrapper documentTitle="App" element={<Parent />} />
</div>
</DocumentTitleProvider>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment