From 24b1ebbc21ca2eaa92bd6b5b8c15ab0e7577f5a0 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Wed, 10 Nov 2021 12:23:27 +1100 Subject: [PATCH] [WIP]Use Isomorphic effect (#1583) * Use Isomorphic effect * Create brown-squids-unite.md * Fix eslint rules * Make it typescript * Add back the eslint disables * Fix up the tests and make the method more robust * Fix lint Co-authored-by: Pavithra Kodmad --- .changeset/brown-squids-unite.md | 5 +++++ src/Overlay.tsx | 3 ++- src/Portal/Portal.tsx | 3 ++- src/hooks/useAnchoredPosition.ts | 3 ++- src/hooks/useCombinedRefs.ts | 6 +++--- src/hooks/useResizeObserver.ts | 4 ++-- src/utils/useIsomorphicLayoutEffect.ts | 10 ++++++++++ 7 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 .changeset/brown-squids-unite.md create mode 100644 src/utils/useIsomorphicLayoutEffect.ts diff --git a/.changeset/brown-squids-unite.md b/.changeset/brown-squids-unite.md new file mode 100644 index 00000000000..660049b1b02 --- /dev/null +++ b/.changeset/brown-squids-unite.md @@ -0,0 +1,5 @@ +--- +"@primer/components": patch +--- + +Add a utility to provide useIsoMorphicEffect function and use that instead of useLayoutEffect everywhere diff --git a/src/Overlay.tsx b/src/Overlay.tsx index 534ccf13b1f..c32cc2a0bf6 100644 --- a/src/Overlay.tsx +++ b/src/Overlay.tsx @@ -1,7 +1,8 @@ import styled from 'styled-components' -import React, {ReactElement, useEffect, useLayoutEffect, useRef} from 'react' +import React, {ReactElement, useEffect, useRef} from 'react' import {get, COMMON, SystemPositionProps, SystemCommonProps} from './constants' import {ComponentProps} from './utils/types' +import useLayoutEffect from './utils/useIsomorphicLayoutEffect' import {useOverlay, TouchOrMouseEvent} from './hooks' import Portal from './Portal' import sx, {SxProp} from './sx' diff --git a/src/Portal/Portal.tsx b/src/Portal/Portal.tsx index a2eaf32fecc..bc5445e9143 100644 --- a/src/Portal/Portal.tsx +++ b/src/Portal/Portal.tsx @@ -1,5 +1,6 @@ import React from 'react' import {createPortal} from 'react-dom' +import useLayoutEffect from '../utils/useIsomorphicLayoutEffect' const PRIMER_PORTAL_ROOT_ID = '__primerPortalRoot__' const DEFAULT_PORTAL_CONTAINER_NAME = '__default__' @@ -69,7 +70,7 @@ export const Portal: React.FC = ({children, onMount, containerName: hostElement.style.zIndex = '1' const elementRef = React.useRef(hostElement) - React.useLayoutEffect(() => { + useLayoutEffect(() => { let containerName = _containerName if (containerName === undefined) { containerName = DEFAULT_PORTAL_CONTAINER_NAME diff --git a/src/hooks/useAnchoredPosition.ts b/src/hooks/useAnchoredPosition.ts index 5ff674833a3..4134916316c 100644 --- a/src/hooks/useAnchoredPosition.ts +++ b/src/hooks/useAnchoredPosition.ts @@ -2,6 +2,7 @@ import React from 'react' import {PositionSettings, getAnchoredPosition, AnchorPosition} from '../behaviors/anchoredPosition' import {useProvidedRefOrCreate} from './useProvidedRefOrCreate' import {useResizeObserver} from './useResizeObserver' +import useLayoutEffect from '../utils/useIsomorphicLayoutEffect' export interface AnchoredPositionHookSettings extends Partial { floatingElementRef?: React.RefObject @@ -41,7 +42,7 @@ export function useAnchoredPosition( [floatingElementRef, anchorElementRef, ...dependencies] ) - React.useLayoutEffect(updatePosition, [updatePosition]) + useLayoutEffect(updatePosition, [updatePosition]) useResizeObserver(updatePosition) diff --git a/src/hooks/useCombinedRefs.ts b/src/hooks/useCombinedRefs.ts index 0eedc6beb5e..8eb341ea1a6 100644 --- a/src/hooks/useCombinedRefs.ts +++ b/src/hooks/useCombinedRefs.ts @@ -1,4 +1,5 @@ -import React, {ForwardedRef, useRef} from 'react' +import {ForwardedRef, useRef} from 'react' +import useLayoutEffect from '../utils/useIsomorphicLayoutEffect' /** * Creates a ref by combining multiple constituent refs. The ref returned by this hook @@ -11,7 +12,7 @@ import React, {ForwardedRef, useRef} from 'react' export function useCombinedRefs(...refs: (ForwardedRef | null | undefined)[]) { const combinedRef = useRef(null) - React.useLayoutEffect(() => { + useLayoutEffect(() => { function setRefs(current: T | null = null) { for (const ref of refs) { if (!ref) { @@ -32,7 +33,6 @@ export function useCombinedRefs(...refs: (ForwardedRef | null | undefined) // eslint-disable-next-line react-hooks/exhaustive-deps setRefs(combinedRef.current) } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [...refs, combinedRef.current]) diff --git a/src/hooks/useResizeObserver.ts b/src/hooks/useResizeObserver.ts index c18d9f83453..fee96fcb1c4 100644 --- a/src/hooks/useResizeObserver.ts +++ b/src/hooks/useResizeObserver.ts @@ -1,7 +1,7 @@ -import React from 'react' +import useLayoutEffect from '../utils/useIsomorphicLayoutEffect' export function useResizeObserver(callback: () => void) { - React.useLayoutEffect(() => { + useLayoutEffect(() => { const observer = new window.ResizeObserver(() => callback()) observer.observe(document.documentElement) return () => { diff --git a/src/utils/useIsomorphicLayoutEffect.ts b/src/utils/useIsomorphicLayoutEffect.ts new file mode 100644 index 00000000000..6213d5af4e0 --- /dev/null +++ b/src/utils/useIsomorphicLayoutEffect.ts @@ -0,0 +1,10 @@ +import {useEffect, useLayoutEffect} from 'react' + +const useIsomorphicLayoutEffect = + typeof window !== 'undefined' && + typeof window.document !== 'undefined' && + typeof window.document.createElement !== 'undefined' + ? useLayoutEffect + : useEffect + +export default useIsomorphicLayoutEffect