Skip to content

Commit

Permalink
fix: Update useStyledComponentsTarget to support case where head tag …
Browse files Browse the repository at this point in the history
…is removed. (#412)

## Changes
- Fixed an issue where widget style is not applied due to style tag
being dynamically removed and then re-added in the head tag in a
WordPress like environment

ticket: [AA-772](https://sendbird.atlassian.net/browse/AA-722)

## Additional Notes
- 

## Checklist
Before requesting a code review, please check the following:
- [x] **[Required]** CI has passed all checks.
- [x] **[Required]** A self-review has been conducted to ensure there
are no minor mistakes.
- [x] **[Required]** Unnecessary comments/debugging code have been
removed.
- [x] **[Required]** All requirements specified in the ticket have been
accurately implemented.
- [ ] Ensure the ticket has been updated with the sprint, status, and
story points.
  • Loading branch information
liamcho authored Jan 21, 2025
1 parent a0a4448 commit b1c82a0
Showing 1 changed file with 26 additions and 13 deletions.
39 changes: 26 additions & 13 deletions src/hooks/useStyledComponentsTarget.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useLayoutEffect, useRef, useState } from 'react';
import { useLayoutEffect, useState } from 'react';
import { version } from 'styled-components/package.json';

function isSCTarget(node: Node): node is HTMLStyleElement {
Expand All @@ -9,28 +9,41 @@ function isSCTarget(node: Node): node is HTMLStyleElement {
* This hook observes mutations in the document's head
* When styled-components, which has already been initialized, is re-added to the head, for example `document.head.innerHTML += ''`, the styles may not render correctly.
* Therefore, the target is moved to the body tag.
*
* Similarly, the issue could also rise in below cases and the hook handles them accordingly:
* - If styles are removed from <head>, switch to <body>.
* This is a short-term solution, and in the long run, we plan to remove styled-components altogether.
* */
export function useStyledComponentsTarget() {
const scInitialized = useRef(false);
const [target, setTarget] = useState(document.head);

useLayoutEffect(() => {
const observer = new MutationObserver((mutations) => {
const mutation = mutations.find((it) => it.target === document.head && it.addedNodes.length > 0);

for (const node of mutation?.addedNodes ?? []) {
if (!isSCTarget(node)) continue;

if (scInitialized.current) {
setTarget(document.body);
} else {
scInitialized.current = true;
mutations.forEach((mutation) => {
// Case 1: Detect if styles are added to <head>
if (mutation.target === document.head && mutation.addedNodes.length > 0) {
for (const node of mutation.addedNodes) {
if (isSCTarget(node)) {
console.warn('Styled Components styles re-injected, switching to <body>');
setTarget(document.body);
return;
}
}
}
// Case 2: Detect if styles are removed from <head>
if (mutation.target === document.head && mutation.removedNodes.length > 0) {
for (const node of mutation.removedNodes) {
if (isSCTarget(node)) {
console.warn('Styled Components styles removed, switching to <body>');
setTarget(document.body);
return;
}
}
}
}
});
});

observer.observe(document.head, { childList: true });

return () => observer.disconnect();
}, []);

Expand Down

0 comments on commit b1c82a0

Please sign in to comment.