Skip to content

Commit

Permalink
fix: Undefined HTMLElement is no longer an issue in certain SSR edge …
Browse files Browse the repository at this point in the history
…cases.

Passing in a custom ref would make the hook check for `instanceof HTMLElement`,
which fails in SSR environments. (Node, JSDom)

Fixes #74 #62
  • Loading branch information
ZeeCoder committed Jul 27, 2021
1 parent 9c3f169 commit 599cace
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 20 deletions.
27 changes: 8 additions & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@ function useResolvedElement<T extends HTMLElement>(
subscriber: (element: T) => SubscriberResponse,
refOrElement?: T | RefObject<T> | null
): RefCallback<T> {
// The default ref has to be non-conditionally declared here whether or not
// it'll be used as that's how hooks work.
// @see https://reactjs.org/docs/hooks-rules.html#explanation
let ref: RefObject<T> | null = null; // Default ref
const refElement = useRef<T | null>(null);
const callbackRefElement = useRef<T | null>(null);
const refCallback = useCallback((element: T) => {
const refCallback = useCallback<RefCallback<T>>((element) => {
callbackRefElement.current = element;
callSubscriber();
}, []);
Expand All @@ -36,10 +31,12 @@ function useResolvedElement<T extends HTMLElement>(
let element = null;
if (callbackRefElement.current) {
element = callbackRefElement.current;
} else if (refElement.current) {
element = refElement.current;
} else if (refOrElement instanceof HTMLElement) {
element = refOrElement;
} else if (refOrElement) {
if (refOrElement instanceof HTMLElement) {
element = refOrElement;
} else {
element = refOrElement.current;
}
}

if (lastReportedElementRef.current === element) {
Expand All @@ -59,11 +56,6 @@ function useResolvedElement<T extends HTMLElement>(
}
};

if (refOrElement && !(refOrElement instanceof HTMLElement)) {
// Overriding the default ref with the given one
ref = refOrElement;
}

// On each render, we check whether a ref changed, or if we got a new raw
// element.
useEffect(() => {
Expand All @@ -72,11 +64,8 @@ function useResolvedElement<T extends HTMLElement>(
// the current ref value, but there's no guarantee that the ref value will
// not change later without a render.
// This may or may not be a problem depending on the specific use case.
if (ref) {
refElement.current = ref.current;
}
callSubscriber();
}, [ref, ref?.current, refOrElement]);
}, [refOrElement]);

return refCallback;
}
Expand Down
5 changes: 4 additions & 1 deletion tests/ssr/Test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ const useResizeObserver =
baseUseResizeObserver.default || baseUseResizeObserver;

module.exports = function Test() {
const { ref, width = 1, height = 2 } = useResizeObserver();
// Pasting in our own ref here, as this used to cause issues with SSR:
// @see https://github.com/ZeeCoder/use-resize-observer/issues/74
const ref = React.useRef(null);
const { width = 1, height = 2 } = useResizeObserver({ ref });

return React.createElement(
"div",
Expand Down

0 comments on commit 599cace

Please sign in to comment.