Skip to content

Commit

Permalink
make useLink concurrent safe (#79)
Browse files Browse the repository at this point in the history
* make useLink concurrent safe

* remove JSON,stringify

* add changest
  • Loading branch information
JoviDeCroock committed Apr 28, 2023
1 parent a6a9a78 commit 689e0b6
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-kings-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'hoofd': minor
---

Make `useLink` concurrent safe by only re-using `link` tags carrying `data-hoofd="1"`, these would come from hydration as hoofd will add these to the static export
8 changes: 5 additions & 3 deletions __tests__/ssr.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ describe('ssr', () => {
expect(lang).toEqual('nl');
expect(title).toEqual('hi');
expect(metas).toEqual([{ content: 'hi', property: 'fb:admins' }]);
expect(links).toEqual([{ rel: 'stylesheet', href: 'x' }]);
expect(links).toEqual([
{ 'data-hoofd': '1', rel: 'stylesheet', href: 'x' },
]);
expect(scripts).toEqual([
{
crossorigin: 'anonymous',
Expand Down Expand Up @@ -145,8 +147,8 @@ describe('ssr', () => {
expect(title).toEqual('bye');
expect(metas).toEqual([{ content: 'bye', property: 'fb:admins' }]);
expect(links).toEqual([
{ rel: 'stylesheet', href: 'x' },
{ rel: 'stylesheet', href: 'y' },
{ 'data-hoofd': '1', rel: 'stylesheet', href: 'x' },
{ 'data-hoofd': '1', rel: 'stylesheet', href: 'y' },
]);
expect(scripts).toEqual([
{
Expand Down
2 changes: 1 addition & 1 deletion src/dispatcher/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ export const createDispatcher = () => {
return {
lang,
title,
links,
links: links.map((x) => ({ ...x, ['data-hoofd']: '1' })),
scripts,
metas: metas.map((meta) =>
meta.keyword === 'charset'
Expand Down
25 changes: 7 additions & 18 deletions src/hooks/useLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export interface LinkOptions {

export const useLink = (options: LinkOptions) => {
const dispatcher = useContext(DispatcherContext);

const hasMounted = useRef(false);
const node = useRef<Element | undefined>();
const originalOptions = useRef<LinkOptions | undefined>();

if (isServerSide && !hasMounted.current) {
dispatcher._addToQueue(LINK, options as any);
Expand All @@ -39,14 +39,16 @@ export const useLink = (options: LinkOptions) => {
options.crossorigin,
options.type,
options.hreflang,
options.sizes,
]);

useEffect(() => {
hasMounted.current = true;
const preExistingElements = document.querySelectorAll(
`link[rel="${options.rel}"]`
`link[data-hoofd="1"]`
);

// We should be able to recover from SSR like this
preExistingElements.forEach((x) => {
let found = true;
Object.keys(options).forEach((key) => {
Expand All @@ -61,13 +63,7 @@ export const useLink = (options: LinkOptions) => {
}
});

if (node.current) {
originalOptions.current = Object.keys(options).reduce((acc, key) => {
// @ts-ignore
acc[key] = node.current!.getAttribute(key);
return acc;
}, {} as LinkOptions);
} else {
if (!node.current) {
node.current = document.createElement('link');
Object.keys(options).forEach((key) => {
// @ts-ignore
Expand All @@ -78,16 +74,9 @@ export const useLink = (options: LinkOptions) => {

return () => {
hasMounted.current = false;
if (originalOptions.current) {
Object.keys(originalOptions.current).forEach((key) => {
(node.current as Element).setAttribute(
key,
// @ts-ignore
originalOptions.current[key]
);
});
} else {
if (node.current) {
document.head.removeChild(node.current as Element);
node.current = undefined;
}
};
}, []);
Expand Down

0 comments on commit 689e0b6

Please sign in to comment.