Skip to content

Commit

Permalink
refactor(react): add useSetTimeout to reduce code (#158)
Browse files Browse the repository at this point in the history
* refactor(react): add useSetTimeout to reduce code

* Create friendly-ants-grab.md
  • Loading branch information
manudeli authored Sep 22, 2023
1 parent da0bd52 commit 2c30f6d
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/friendly-ants-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@suspensive/react": patch
---

refactor(react): add useSetTimeout to reduce code
10 changes: 3 additions & 7 deletions packages/react/src/Delay.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ComponentProps, ComponentType, PropsWithChildren, createContext, useContext, useEffect, useState } from 'react'
import { ComponentProps, ComponentType, PropsWithChildren, createContext, useContext, useState } from 'react'
import { useSetTimeout } from './hooks'
import { PropsWithoutChildren } from './types'

type DelayProps = PropsWithChildren<{
Expand All @@ -8,12 +9,7 @@ export const Delay = ({ ms, children }: DelayProps) => {
const delayContextValue = useContext(DelayContext)
const delayMs = ms ?? delayContextValue.ms ?? 0
const [isDelayed, setIsDelayed] = useState(delayMs === 0)

useEffect(() => {
const timerId = setTimeout(() => setIsDelayed(true), delayMs)
return () => clearTimeout(timerId)
}, [delayMs])

useSetTimeout(() => setIsDelayed(true), delayMs)
return <>{isDelayed ? children : null}</>
}

Expand Down
1 change: 1 addition & 0 deletions packages/react/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { useIsMounted } from './useIsMounted'
export { useKey } from './useKey'
export { usePrevious } from './usePrevious'
export { useIsChanged } from './useIsChanged'
export { useSetTimeout } from './useSetTimeout'
22 changes: 22 additions & 0 deletions packages/react/src/hooks/useSetTimeout.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { act, renderHook } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { MS_100 } from '../utils/toTest'
import { useSetTimeout } from '.'

vi.useFakeTimers()

describe('useSetTimeout', () => {
it('should run given function once after given timeout', () => {
const fn = vi.fn()
const rendered = renderHook(() => useSetTimeout(fn, MS_100))
expect(fn).toHaveBeenCalledTimes(0)
act(() => vi.advanceTimersByTime(MS_100))
expect(fn).toHaveBeenCalledTimes(1)
act(() => vi.advanceTimersByTime(MS_100))
expect(fn).toHaveBeenCalledTimes(1)
rendered.rerender()
expect(fn).toHaveBeenCalledTimes(1)
act(() => vi.advanceTimersByTime(MS_100))
expect(fn).toHaveBeenCalledTimes(1)
})
})
7 changes: 7 additions & 0 deletions packages/react/src/hooks/useSetTimeout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useEffect } from 'react'

export const useSetTimeout = (fn: (...args: []) => void, delay: number) =>
useEffect(() => {
const timeout = setTimeout(fn, delay)
return () => clearTimeout(timeout)
}, [fn, delay])
12 changes: 4 additions & 8 deletions packages/react/src/utils/toTest.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PropsWithChildren, ReactNode, useEffect, useState } from 'react'
import { PropsWithChildren, ReactNode, useState } from 'react'
import { useSetTimeout } from '../hooks'

const suspendIsNeed = { current: true }
type SuspendProps = { during: number; toShow?: ReactNode }
Expand All @@ -24,9 +25,7 @@ export const ThrowError = ({ message, after, children }: ThrowErrorProps) => {
if (isNeedError) {
throw new Error(message)
}
useEffect(() => {
setTimeout(() => setIsNeedError(true), after)
}, [after])
useSetTimeout(() => setIsNeedError(true), after)
return <>{children}</>
}

Expand All @@ -36,10 +35,7 @@ export const ThrowNull = ({ after, children }: ThrowNullProps) => {
if (isNeedError) {
throw null
}
useEffect(() => {
const timerId = setTimeout(() => setIsNeedError(true), after)
return () => clearTimeout(timerId)
}, [after])
useSetTimeout(() => setIsNeedError(true), after)
return <>{children}</>
}

Expand Down

1 comment on commit 2c30f6d

@vercel
Copy link

@vercel vercel bot commented on 2c30f6d Sep 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visualization – ./websites/visualization

visualization.suspensive.org
visualization-git-main-suspensive.vercel.app
visualization-suspensive.vercel.app

Please sign in to comment.