diff --git a/packages/react-query/CHANGELOG.md b/packages/react-query/CHANGELOG.md index d286e9029..9e4a9a6b8 100644 --- a/packages/react-query/CHANGELOG.md +++ b/packages/react-query/CHANGELOG.md @@ -1,5 +1,12 @@ # @suspensive/react-query +## 1.17.4 + +### Patch Changes + +- Updated dependencies [70d8128] + - @suspensive/react@1.17.4 + ## 1.17.3 ### Patch Changes diff --git a/packages/react-query/package.json b/packages/react-query/package.json index db4afe225..ac6340efe 100644 --- a/packages/react-query/package.json +++ b/packages/react-query/package.json @@ -1,6 +1,6 @@ { "name": "@suspensive/react-query", - "version": "1.17.3", + "version": "1.17.4", "description": "Useful helpers for @tanstack/react-query with suspense", "keywords": [ "suspensive", @@ -70,7 +70,7 @@ "tsd": "^0.28.1" }, "peerDependencies": { - "@suspensive/react": "workspace:^1.17.3", + "@suspensive/react": "workspace:^1.17.4", "@tanstack/react-query": "^4", "react": "^16.8 || ^17 || ^18" }, diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 7acddd431..9286f1415 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,11 @@ # @suspensive/react +## 1.17.4 + +### Patch Changes + +- 70d8128: fix(react): convert Suspense.CSROnly's useEffect into useIsomorphicLayoutEffect to prevent unnecessary layout shift + ## 1.17.3 ### Patch Changes diff --git a/packages/react/package.json b/packages/react/package.json index 3274a4a79..a3f1b981b 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@suspensive/react", - "version": "1.17.3", + "version": "1.17.4", "description": "Useful interfaces for React Suspense", "keywords": [ "suspensive", diff --git a/packages/react/src/Suspense.tsx b/packages/react/src/Suspense.tsx index 0a5ca8f10..9d1a998bb 100644 --- a/packages/react/src/Suspense.tsx +++ b/packages/react/src/Suspense.tsx @@ -1,6 +1,6 @@ import type { ComponentProps, ComponentType, ReactNode, SuspenseProps as ReactSuspenseProps } from 'react' import { Suspense as ReactSuspense, createContext, useContext } from 'react' -import { useIsMounted } from './hooks' +import { useIsClient } from './hooks' import type { PropsWithoutChildren } from './types' export type SuspenseProps = ReactSuspenseProps @@ -21,10 +21,10 @@ if (process.env.NODE_ENV !== 'production') { DefaultSuspense.displayName = 'Suspense' } const CSROnlySuspense = (props: SuspenseProps) => { - const isMounted = useIsMounted() + const isClient = useIsClient() const fallback = useFallbackWithContext(props.fallback) - return isMounted ? : <>{fallback} + return isClient ? : <>{fallback} } if (process.env.NODE_ENV !== 'production') { CSROnlySuspense.displayName = 'Suspense.CSROnly' diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index 5e354cd50..825ac85ad 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -1,5 +1,5 @@ export { useIsChanged } from './useIsChanged' -export { useIsMounted } from './useIsMounted' +export { useIsClient } from './useIsClient' export { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect' export { useKey } from './useKey' export { usePrevious } from './usePrevious' diff --git a/packages/react/src/hooks/useIsClient.spec.ts b/packages/react/src/hooks/useIsClient.spec.ts new file mode 100644 index 000000000..ce705580b --- /dev/null +++ b/packages/react/src/hooks/useIsClient.spec.ts @@ -0,0 +1,12 @@ +import { renderHook } from '@testing-library/react' +import { useIsClient } from '.' + +describe('useIsClient', () => { + it('should return true when client side painting start', () => { + const { + result: { current: isClient }, + } = renderHook(() => useIsClient()) + + expect(isClient).toBe(true) + }) +}) diff --git a/packages/react/src/hooks/useIsClient.ts b/packages/react/src/hooks/useIsClient.ts new file mode 100644 index 000000000..3329a6390 --- /dev/null +++ b/packages/react/src/hooks/useIsClient.ts @@ -0,0 +1,12 @@ +import { useState } from 'react' +import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect' + +export const useIsClient = () => { + const [isClient, setIsClient] = useState(false) + + useIsomorphicLayoutEffect(() => { + setIsClient(true) + }, []) + + return isClient +} diff --git a/packages/react/src/hooks/useIsMounted.spec.ts b/packages/react/src/hooks/useIsMounted.spec.ts deleted file mode 100644 index 5954eaacb..000000000 --- a/packages/react/src/hooks/useIsMounted.spec.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { renderHook } from '@testing-library/react' -import { useIsMounted } from '.' - -describe('useIsMounted', () => { - it('should return true when component is mounted', () => { - const { - result: { current: isMounted }, - } = renderHook(() => useIsMounted()) - - expect(isMounted).toBe(true) - }) -}) diff --git a/packages/react/src/hooks/useIsMounted.ts b/packages/react/src/hooks/useIsMounted.ts deleted file mode 100644 index 3ce612fe5..000000000 --- a/packages/react/src/hooks/useIsMounted.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useEffect, useState } from 'react' - -export const useIsMounted = () => { - const [isMounted, setIsMounted] = useState(false) - - useEffect(() => { - setIsMounted(true) - }, []) - - return isMounted -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52125b1ad..0a531f331 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -343,13 +343,13 @@ importers: specifier: ^1.3.9 version: 1.3.9(@emotion/react@11.11.0)(react@18.2.0) '@suspensive/react': - specifier: workspace:1.17.3 + specifier: workspace:1.17.4 version: link:../../packages/react '@suspensive/react-await': specifier: workspace:0.0.1 version: link:../../packages/react-await '@suspensive/react-query': - specifier: workspace:1.17.3 + specifier: workspace:1.17.4 version: link:../../packages/react-query '@tanstack/react-query': specifier: ^4.29.5 diff --git a/websites/visualization/package.json b/websites/visualization/package.json index c6e5a2ca6..8f2ee6860 100644 --- a/websites/visualization/package.json +++ b/websites/visualization/package.json @@ -30,9 +30,9 @@ "@emotion/react": "^11.10.8", "@emotion/styled": "^11.10.8", "@jsxcss/emotion": "^1.3.9", - "@suspensive/react": "workspace:1.17.3", + "@suspensive/react": "workspace:1.17.4", "@suspensive/react-await": "workspace:0.0.1", - "@suspensive/react-query": "workspace:1.17.3", + "@suspensive/react-query": "workspace:1.17.4", "@tanstack/react-query": "^4.29.5", "@tanstack/react-query-devtools": "^4.29.5", "@vercel/analytics": "^1.1.1",