diff --git a/src/components/Breadcrumbs/Breadcrumbs.tsx b/src/components/Breadcrumbs/Breadcrumbs.tsx index 70a8122e1c..3e10908547 100644 --- a/src/components/Breadcrumbs/Breadcrumbs.tsx +++ b/src/components/Breadcrumbs/Breadcrumbs.tsx @@ -2,6 +2,8 @@ import * as React from 'react'; +import {useLayoutEffect} from 'src/hooks/private'; + import {useForkRef, useResizeObserver} from '../../hooks'; import type {PopupPlacement} from '../Popup'; import type {AriaLabelingProps, DOMProps, Key, QAProps} from '../types'; @@ -131,7 +133,7 @@ export const Breadcrumbs = React.forwardRef(function Breadcrumbs( }); const lastChildren = React.useRef(null); - React.useLayoutEffect(() => { + useLayoutEffect(() => { if (calculated && props.children !== lastChildren.current) { lastChildren.current = props.children; setVisibleItemsCount(items.length); @@ -139,7 +141,7 @@ export const Breadcrumbs = React.forwardRef(function Breadcrumbs( } }, [calculated, items.length, props.children]); - React.useLayoutEffect(() => { + useLayoutEffect(() => { if (!calculated) { recalculate(visibleItemsCount); } diff --git a/src/components/TreeSelect/TreeSelect.tsx b/src/components/TreeSelect/TreeSelect.tsx index 17a1c1a60a..464d702cd1 100644 --- a/src/components/TreeSelect/TreeSelect.tsx +++ b/src/components/TreeSelect/TreeSelect.tsx @@ -2,6 +2,8 @@ import * as React from 'react'; +import {useLayoutEffect} from 'src/hooks/private'; + import {useFocusWithin, useForkRef, useUniqId} from '../../hooks'; import {useOpenState} from '../../hooks/useSelect/useOpenState'; import {SelectControl} from '../Select/components'; @@ -147,7 +149,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect { + useLayoutEffect(() => { if (open) { // for some reason popup position on page may be wrong calculated. `preventScroll` prevent page gap in that cases containerRef.current?.focus({preventScroll: true}); diff --git a/src/components/lab/Virtualizer/useLoadMore.tsx b/src/components/lab/Virtualizer/useLoadMore.tsx index 9896aa6bf4..3ff2eaa3f0 100644 --- a/src/components/lab/Virtualizer/useLoadMore.tsx +++ b/src/components/lab/Virtualizer/useLoadMore.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; +import {useLayoutEffect} from 'src/hooks/private'; + export interface Loadable { /** Whether the items are currently loading. */ loading?: boolean; @@ -11,7 +13,6 @@ export interface LoadMoreOptions extends Loadable { /** * The amount of offset from bottom that should trigger load more. * The value is multiplied to the size of the visible area. - * * @default 1 */ scrollOffset?: number; @@ -50,7 +51,7 @@ export function useLoadMore( }, [scrollContainerRef, onLoadMore, scrollOffset]); const prevLoadingPropRef = React.useRef(loading); - React.useLayoutEffect(() => { + useLayoutEffect(() => { if (loading !== prevLoadingPropRef.current) { isLoadingRef.current = loading; prevLoadingPropRef.current = loading; diff --git a/src/components/layout/hooks/useCurrentActiveMediaQuery.tsx b/src/components/layout/hooks/useCurrentActiveMediaQuery.tsx index 1312d4122b..e63ffe7c71 100644 --- a/src/components/layout/hooks/useCurrentActiveMediaQuery.tsx +++ b/src/components/layout/hooks/useCurrentActiveMediaQuery.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; +import {useLayoutEffect} from 'src/hooks/private'; + import type {MediaProps, MediaType} from '../types'; export const mockMediaQueryList: MediaQueryList = { @@ -88,7 +90,7 @@ export const useCurrentActiveMediaQuery = ( initialMediaQuery ?? (fixBreakpoints ? 'xs' : 's'), ); - React.useLayoutEffect(() => { + useLayoutEffect(() => { const queries = new Queries(breakpointsMap, fixBreakpoints); const setState = () => { diff --git a/src/components/theme/ThemeProvider.tsx b/src/components/theme/ThemeProvider.tsx index a90b453822..69c276ee50 100644 --- a/src/components/theme/ThemeProvider.tsx +++ b/src/components/theme/ThemeProvider.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; +import {useLayoutEffect} from '../../hooks/private'; import {PrivateLayoutProvider} from '../layout/LayoutProvider/LayoutProvider'; import type {PrivateLayoutProviderProps} from '../layout/LayoutProvider/LayoutProvider'; import {block} from '../utils/cn'; @@ -66,7 +67,7 @@ export function ThemeProvider({ const prevRootClassName = React.useRef(''); - React.useLayoutEffect(() => { + useLayoutEffect(() => { if (!scoped) { updateBodyClassName({ theme: themeValue, diff --git a/src/components/useList/hooks/useListKeydown.tsx b/src/components/useList/hooks/useListKeydown.tsx index 4a1c0f301f..d78b0d005e 100644 --- a/src/components/useList/hooks/useListKeydown.tsx +++ b/src/components/useList/hooks/useListKeydown.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; +import {useLayoutEffect} from 'src/hooks/private'; + import {KeyCode} from '../../../constants'; import type {ListOnItemClick, UseListResult} from '../types'; import {findNextIndex} from '../utils/findNextIndex'; @@ -58,7 +60,7 @@ export const useListKeydown = ({containerRef, onItemClick, enabled, list}: UseLi ], ); - React.useLayoutEffect(() => { + useLayoutEffect(() => { const anchor = containerRef?.current; if (enabled || !anchor) { diff --git a/src/hooks/private/index.ts b/src/hooks/private/index.ts index 315c180e75..85a8d9675b 100644 --- a/src/hooks/private/index.ts +++ b/src/hooks/private/index.ts @@ -10,3 +10,4 @@ export * from './usePrevious'; export * from './useRadio'; export * from './useRadioGroup'; export * from './useUpdateEffect'; +export * from './useIsomorphicLayoutEffect'; diff --git a/src/hooks/private/useCheckbox/useCheckbox.ts b/src/hooks/private/useCheckbox/useCheckbox.ts index c40045fffd..7843baee65 100644 --- a/src/hooks/private/useCheckbox/useCheckbox.ts +++ b/src/hooks/private/useCheckbox/useCheckbox.ts @@ -1,5 +1,7 @@ import * as React from 'react'; +import {useLayoutEffect} from 'src/hooks/private'; + import {useControlledState, useForkRef} from '../..'; import type {ControlProps} from '../../../components/types'; import {eventBroker} from '../../../components/utils/event-broker'; @@ -41,7 +43,7 @@ export function useCheckbox({ const handleRef = useForkRef(controlRef, innerControlRef, fieldRef); - React.useLayoutEffect(() => { + useLayoutEffect(() => { if (innerControlRef.current) { innerControlRef.current.indeterminate = Boolean(indeterminate); } diff --git a/src/hooks/private/useElementSize/useElementSize.ts b/src/hooks/private/useElementSize/useElementSize.ts index 18ca7656b4..492f08da00 100644 --- a/src/hooks/private/useElementSize/useElementSize.ts +++ b/src/hooks/private/useElementSize/useElementSize.ts @@ -3,6 +3,8 @@ import * as React from 'react'; import round from 'lodash/round'; import throttle from 'lodash/throttle'; +import {useLayoutEffect} from 'src/hooks/private'; + const RESIZE_THROTTLE = 16; const ROUND_PRECISION = 2; @@ -23,7 +25,7 @@ export function useElementSize( height: 0, }); - React.useLayoutEffect(() => { + useLayoutEffect(() => { const element = ref?.current; if (!element) { return undefined; diff --git a/src/hooks/private/useIsomorphicLayoutEffect/index.ts b/src/hooks/private/useIsomorphicLayoutEffect/index.ts new file mode 100644 index 0000000000..369d269151 --- /dev/null +++ b/src/hooks/private/useIsomorphicLayoutEffect/index.ts @@ -0,0 +1 @@ +export {useLayoutEffect} from './useIsomorphicLayoutEffect'; diff --git a/src/hooks/private/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts b/src/hooks/private/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts new file mode 100644 index 0000000000..d9184c73cf --- /dev/null +++ b/src/hooks/private/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts @@ -0,0 +1,3 @@ +import * as React from 'react'; + +export const useLayoutEffect = typeof window === 'undefined' ? () => {} : React.useLayoutEffect; diff --git a/src/hooks/useListNavigation/useListNavigation.ts b/src/hooks/useListNavigation/useListNavigation.ts index 5571137ba0..c351235709 100644 --- a/src/hooks/useListNavigation/useListNavigation.ts +++ b/src/hooks/useListNavigation/useListNavigation.ts @@ -1,5 +1,7 @@ import * as React from 'react'; +import {useLayoutEffect} from 'src/hooks/private'; + import {KeyCode} from '../../constants'; import {moveBack} from './moveBack'; @@ -46,7 +48,7 @@ export function useListNavigation({ } }, [items, reset]); - React.useLayoutEffect(() => { + useLayoutEffect(() => { if (disabled) { return undefined; }