From f3ada4856cfb16d54c9bb51eef022c927c6dfd68 Mon Sep 17 00:00:00 2001 From: Kabir Sarin Date: Mon, 12 Oct 2020 11:28:02 -0600 Subject: [PATCH 1/6] Add strict: true to tsconfig.json --- tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index ccbdd31..e5310cf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "declaration": true, "declarationDir": "./types", "emitDeclarationOnly": true, - "jsx": "preserve" + "jsx": "preserve", + "strict": true } } From 33e20382e0c36d122f6d14cbbc6183c0c7d9e5f3 Mon Sep 17 00:00:00 2001 From: Kabir Sarin Date: Mon, 12 Oct 2020 11:30:30 -0600 Subject: [PATCH 2/6] Add idleCallback type, remove ts-ignore statements --- src/index.tsx | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 8d572d5..8e038b6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,6 +2,25 @@ import * as React from "react"; import { isBrowser, isDev } from "./constants.macro"; +type RequestIdleCallbackHandle = number; +type RequestIdleCallbackOptions = { + timeout: number; +}; +type RequestIdleCallbackDeadline = { + readonly didTimeout: boolean; + timeRemaining: () => number; +}; + +declare global { + interface Window { + requestIdleCallback?: ( + callback: (deadline: RequestIdleCallbackDeadline) => void, + opts?: RequestIdleCallbackOptions + ) => RequestIdleCallbackHandle; + cancelIdleCallback?: (handle: RequestIdleCallbackHandle) => void; + } +} + export type LazyProps = { ssrOnly?: boolean; whenIdle?: boolean; @@ -97,13 +116,14 @@ function LazyHydrate(props: Props) { } if (whenIdle) { - // @ts-ignore - if (requestIdleCallback) { - // @ts-ignore - const idleCallbackId = requestIdleCallback(hydrate, { timeout: 500 }); + if (window.requestIdleCallback) { + const idleCallbackId = window.requestIdleCallback(hydrate, { + timeout: 500 + }); cleanupFns.push(() => { - // @ts-ignore - cancelIdleCallback(idleCallbackId); + if (window.cancelIdleCallback) { + window.cancelIdleCallback(idleCallbackId); + } }); } else { const id = setTimeout(hydrate, 2000); From 6aa5883598e3d069416ee6e0aa5b4ee3249ca7d9 Mon Sep 17 00:00:00 2001 From: Kabir Sarin Date: Mon, 12 Oct 2020 11:31:48 -0600 Subject: [PATCH 3/6] Fix ts strict null check errors --- src/index.tsx | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 8e038b6..bf33038 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -93,7 +93,7 @@ function LazyHydrate(props: Props) { useIsomorphicLayoutEffect(() => { // No SSR Content - if (!childRef.current.hasChildNodes()) { + if (!childRef.current?.hasChildNodes()) { setHydrated(true); } }, []); @@ -103,7 +103,7 @@ function LazyHydrate(props: Props) { const cleanupFns: VoidFunction[] = []; function cleanup() { while (cleanupFns.length) { - cleanupFns.pop()(); + cleanupFns.pop()!(); } } function hydrate() { @@ -136,7 +136,7 @@ function LazyHydrate(props: Props) { let events = Array.isArray(on) ? on.slice() : [on]; if (whenVisible) { - if (io && childRef.current.childElementCount) { + if (io && childRef.current?.childElementCount) { // As root node does not have any box model, it cannot intersect. const el = childRef.current.children[0]; io.observe(el); @@ -150,16 +150,21 @@ function LazyHydrate(props: Props) { } } - events.forEach(event => { - childRef.current.addEventListener(event, hydrate, { - once: true, - capture: true, - passive: true - }); - cleanupFns.push(() => { - childRef.current.removeEventListener(event, hydrate, { capture: true }); + const elToListenOn = childRef.current; + if (elToListenOn) { + events.forEach(event => { + elToListenOn.addEventListener(event, hydrate, { + once: true, + capture: true, + passive: true + }); + cleanupFns.push(() => { + elToListenOn.removeEventListener(event, hydrate, { + capture: true + }); + }); }); - }); + } return cleanup; }, [hydrated, on, ssrOnly, whenIdle, whenVisible, didHydrate, promise]); From 45758f5be7270d0cb68630b18d5c06074ebd4bb0 Mon Sep 17 00:00:00 2001 From: Kabir Sarin Date: Mon, 12 Oct 2020 11:34:10 -0600 Subject: [PATCH 4/6] Use proper React.FunctionComponent type --- src/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index bf33038..b3e6efc 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -59,7 +59,7 @@ const useIsomorphicLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect; -function LazyHydrate(props: Props) { +const LazyHydrate: React.FunctionComponent = function(props) { const childRef = React.useRef(null); // Always render on server @@ -189,6 +189,6 @@ function LazyHydrate(props: Props) { /> ); } -} +}; export default LazyHydrate; From 354bc2aeb42f3a6d761f323355e66bed29283555 Mon Sep 17 00:00:00 2001 From: Kabir Sarin Date: Mon, 12 Oct 2020 11:34:59 -0600 Subject: [PATCH 5/6] If noWrapper, render children inside a fragment --- src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index b3e6efc..8457b14 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -171,7 +171,7 @@ const LazyHydrate: React.FunctionComponent = function(props) { if (hydrated) { if (noWrapper) { - return children; + return <>{children}; } return (
From 60d2e68b71db205ca769d83c1bc988790907801a Mon Sep 17 00:00:00 2001 From: Kabir Sarin Date: Mon, 12 Oct 2020 11:42:21 -0600 Subject: [PATCH 6/6] Use ? syntax instead of elToListenOn if-check --- src/index.tsx | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 8457b14..b56c990 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -150,21 +150,18 @@ const LazyHydrate: React.FunctionComponent = function(props) { } } - const elToListenOn = childRef.current; - if (elToListenOn) { - events.forEach(event => { - elToListenOn.addEventListener(event, hydrate, { - once: true, - capture: true, - passive: true - }); - cleanupFns.push(() => { - elToListenOn.removeEventListener(event, hydrate, { - capture: true - }); + events.forEach(event => { + childRef.current?.addEventListener(event, hydrate, { + once: true, + capture: true, + passive: true + }); + cleanupFns.push(() => { + childRef.current?.removeEventListener(event, hydrate, { + capture: true }); }); - } + }); return cleanup; }, [hydrated, on, ssrOnly, whenIdle, whenVisible, didHydrate, promise]);