Skip to content

Instantly share code, notes, and snippets.

@HugeLetters
Last active September 12, 2023 05:02
Show Gist options
  • Save HugeLetters/357f47358400e1e4c70aacddbd8a5cf5 to your computer and use it in GitHub Desktop.
Save HugeLetters/357f47358400e1e4c70aacddbd8a5cf5 to your computer and use it in GitHub Desktop.
Dynamic Delcarative Header
import { contentStackAtom } from "@/hooks/useHeader";
import { useAtomValue } from "jotai";
export default function Header() {
const stack = useAtomValue(contentStackAtom).filter((node) => !!node.content);
return (
<header>
{stack.at(-1)?.content ?? "App Title"}
</header>
);
}
import { immerAtom } from "@/utils/immer";
import { useSetAtom } from "jotai";
import { useEffect, useId, type ReactNode } from "react";
export default function useHeader(content: ReactNode): void {
const setContentStack = useSetAtom(contentStackAtom);
const id = useId();
useEffect(() => {
setContentStack((x) => {
const current = x.find((x) => x.id === id);
if (!current) {
x.push({ content, id });
return;
}
current.content = content;
});
}, [id, setContentStack, content]);
useEffect(() => {
return () => {
setContentStack((x) => x.filter((x) => x.id !== id));
};
}, [id, setContentStack]);
}
export const contentStackAtom = immerAtom<Array<{ content: ReactNode; id: string }>>([]);
@HugeLetters
Copy link
Author

HugeLetters commented Sep 10, 2023

A prototype for my idea to change app header's content dynamically in a declarative manner.

Put useHeader wherever you need to update Header contents. The last component to use it in a hierarchy "wins"

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