Skip to content

Commit

Permalink
refactor(react): use direct undefined comparison for fallback in `<…
Browse files Browse the repository at this point in the history
…Delay/>` and `<Suspense/>` components (#1302)

# Overview

Previously, `typeof` was used to check if `fallback` was `undefined`,
but now it directly compares against `undefined` for improved
efficiency. Additionally, added missing test cases for the `fallback`
functionality.

## PR Checklist
- [X] I did below actions if need

1. I read the [Contributing
Guide](https://github.com/toss/suspensive/blob/main/CONTRIBUTING.md)
2. I added documents and tests.

## Additional

I was impressed by how `defaultProps` can be conveniently managed using
`useContext`! I learned a lot thanks to this.

---------

Co-authored-by: Jonghyeon Ko <[email protected]>
  • Loading branch information
dayongkr and manudeli authored Oct 11, 2024
1 parent 51b2308 commit 5044c94
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/flat-eagles-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@suspensive/react": patch
---

refactor(react): use direct `undefined` comparison for fallback in `<Delay/>` and `<Suspense/>`
10 changes: 10 additions & 0 deletions packages/react/src/Delay.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { render, screen, waitFor } from '@testing-library/react'
import ms from 'ms'
import { DefaultProps, DefaultPropsProvider } from './DefaultProps'
import { Delay } from './Delay'
import { Message_Delay_ms_prop_should_be_greater_than_or_equal_to_0, SuspensiveError } from './models/SuspensiveError'
import { CustomError, TEXT } from './test-utils'
Expand Down Expand Up @@ -53,4 +54,13 @@ describe('<Delay/>', () => {
expect(error).not.toBeInstanceOf(CustomError)
}
})
it('should use `defaultProps.fallback` if no fallback prop is passed', () => {
const defaultProps = new DefaultProps({ Delay: { fallback: 'defaultFallback' } })
render(
<DefaultPropsProvider defaultProps={defaultProps}>
<Delay ms={1}>{TEXT}</Delay>
</DefaultPropsProvider>
)
expect(screen.queryByText('defaultFallback')).toBeInTheDocument()
})
})
8 changes: 3 additions & 5 deletions packages/react/src/Delay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,16 @@ export interface DelayProps extends PropsWithChildren {
}

export const Delay = (props: DelayProps) => {
if (process.env.NODE_ENV === 'development') {
if (typeof props.ms === 'number') {
SuspensiveError.assert(props.ms >= 0, Message_Delay_ms_prop_should_be_greater_than_or_equal_to_0)
}
if (process.env.NODE_ENV === 'development' && typeof props.ms === 'number') {
SuspensiveError.assert(props.ms >= 0, Message_Delay_ms_prop_should_be_greater_than_or_equal_to_0)
}
const defaultProps = useContext(DelayDefaultPropsContext)
const ms = props.ms ?? defaultProps.ms ?? 0

const [isDelaying, setIsDelaying] = useState(ms > 0)
useTimeout(() => setIsDelaying(false), ms)

const fallback = typeof props.fallback === 'undefined' ? defaultProps.fallback : props.fallback
const fallback = props.fallback === undefined ? defaultProps.fallback : props.fallback
return <>{isDelaying ? fallback : props.children}</>
}
if (process.env.NODE_ENV === 'development') {
Expand Down
15 changes: 15 additions & 0 deletions packages/react/src/Suspense.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { render, screen, waitFor } from '@testing-library/react'
import ms from 'ms'
import { DefaultProps, DefaultPropsProvider } from './DefaultProps'
import { Suspense } from './Suspense'
import { FALLBACK, Suspend, TEXT } from './test-utils'

Expand Down Expand Up @@ -60,4 +61,18 @@ describe('<Suspense clientOnly/>', () => {
expect(screen.queryByText(FALLBACK)).not.toBeInTheDocument()
expect(screen.queryByText(TEXT)).toBeInTheDocument()
})
it('should use `defaultProps.fallback` if `fallback` is not provided', () => {
const defaultProps = new DefaultProps({ Suspense: { fallback: 'defaultFallback' } })

render(
<DefaultPropsProvider defaultProps={defaultProps}>
<Suspense clientOnly>
<Suspend during={ms('0.1s')} toShow={TEXT} />
</Suspense>
</DefaultPropsProvider>
)

expect(screen.queryByText('defaultFallback')).toBeInTheDocument()
expect(screen.queryByText(TEXT)).not.toBeInTheDocument()
})
})
4 changes: 1 addition & 3 deletions packages/react/src/Suspense.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ export const Suspense = ({ clientOnly, children, fallback }: SuspenseProps) => {
})

return (
<DefinedSuspense fallback={typeof fallback === 'undefined' ? defaultProps.fallback : fallback}>
{children}
</DefinedSuspense>
<DefinedSuspense fallback={fallback === undefined ? defaultProps.fallback : fallback}>{children}</DefinedSuspense>
)
}
if (process.env.NODE_ENV === 'development') {
Expand Down

0 comments on commit 5044c94

Please sign in to comment.