use-swr-legacy-react.test.tsx
Overview
This file contains test cases specifically targeting the useSWR React hook and related mutation hooks within legacy React environments (React versions 17 and below). The primary focus is to verify that internal flags and behaviors related to legacy React compatibility, such as IS_REACT_LEGACY mode and React’s startTransition API, are correctly enabled and functional when using the swr library.
The tests ensure that useSWR and useSWRMutation hooks behave as expected under legacy React constraints, including proper handling of asynchronous mutations, state updates, and component unmount scenarios. This helps maintain backward compatibility and robustness of the SWR library across different React versions.
Detailed Explanation
Imports and Setup
Testing utilities:
act,screen,render,fireEventfrom@testing-library/reactare used to render components, simulate events, and handle asynchronous state updates in tests.
React mocking:
The React module is mocked with
jest.requireActual('react')to avoid issues with Jest's module isolation and ensure tests run against the actual React implementation.
Utility Function: withLegacyReact
async function withLegacyReact(runner: () => Promise<void>) {
await jest.isolateModulesAsync(async () => {
await runner()
})
}
Purpose: Runs the provided async
runnerfunction inside Jest's isolated module environment.Reason: This isolation is necessary to simulate loading modules fresh in a legacy React environment, ensuring clean state and avoiding cross-test contamination.
Parameters:
runner: An asynchronous function that contains the test logic to execute.
Returns: A
Promise<void>that resolves when the runner completes.Usage Example:
await withLegacyReact(async () => {
// test logic here
});
Test Suites and Test Cases
describe('useSWR - legacy React', () => { ... })
Group of tests focused on verifying SWR behavior with legacy React.
Test Case 1: should enable the IS_REACT_LEGACY flag - startTransition
;(process.env.__SWR_TEST_BUILD ? it.skip : it)(
'should enable the IS_REACT_LEGACY flag - startTransition',
async () => {
await withLegacyReact(async () => {
// Test mutation and trigger
const useSWRMutation = (await import('swr/mutation')).default
const waitForNextTick = () =>
act(() => new Promise(resolve => setTimeout(resolve, 1)))
const key = Math.random().toString()
function Page() {
const { data, trigger } = useSWRMutation(key, () => 'data')
return <button onClick={() => trigger()}>{data || 'pending'}</button>
}
render(<Page />)
// mount
await screen.findByText('pending')
fireEvent.click(screen.getByText('pending'))
await waitForNextTick()
screen.getByText('data')
})
}
)
Purpose: Tests that the
IS_REACT_LEGACYflag is enabled correctly by verifying the behavior ofuseSWRMutation'striggerfunction under legacy React.Key points:
Imports
useSWRMutationdynamically to simulate legacy environment loading.Renders a simple component
Pagewith a button showing "pending" initially.Clicking the button triggers a mutation returning
'data'.Uses
waitForNextTickwrapped with React'sact()to allow state updates.Asserts that the text updates from
"pending"to"data".
Usage: Validates that mutation triggering works and updates state correctly under legacy React with
startTransitionsupport.
Test Case 2: should enable the IS_REACT_LEGACY flag - unmount check
;(process.env.__SWR_TEST_BUILD ? it.skip : it)(
'should enable the IS_REACT_LEGACY flag - unmount check',
async () => {
await withLegacyReact(async () => {
const useSWR = (await import('swr')).default
const key = Math.random().toString()
function Page() {
// No fallback data
const { data } = useSWR(
key,
() =>
new Promise<string>(resolve =>
setTimeout(() => resolve('data'), 100)
),
{
loadingTimeout: 10
}
)
return <p>{data || 'pending'}</p>
}
render(<Page />)
await screen.findByText('data')
})
}
)
Purpose: Tests that the
IS_REACT_LEGACYflag also correctly handles component lifecycle, especially when using asynchronous fetches withuseSWR.Key points:
Imports
useSWRdynamically.Creates a
Pagecomponent usinguseSWRwith a fetcher that resolves with'data'after 100ms.Sets
loadingTimeoutto 10ms to simulate a loading delay.Initially,
datais undefined, so the component shows"pending".After the fetch resolves, the component updates to show
"data".
Usage: Ensures that SWR's internal mechanisms handle asynchronous state updates and unmounting correctly in legacy React.
Important Implementation Details
Dynamic Imports: Both
useSWRanduseSWRMutationare imported dynamically inside the isolated environment to mimic legacy React module loading conditions.Environment Flag (
IS_REACT_LEGACY): The tests indirectly verify that SWR's internal legacy React flag is enabled by checking that asynchronous state transitions and mutations behave as expected.Jest Isolation:
jest.isolateModulesAsyncis used to isolate module state for each test to avoid side effects, crucial for legacy React environment simulation.Conditionally Skipping Tests: Tests are conditionally skipped based on the environment variable
__SWR_TEST_BUILDto avoid running in certain build/test configurations.
Interaction with Other Parts of the System
SWR Library (
swrandswr/mutation): This file tests hooks from the SWR library, ensuring compatibility with legacy React.React Testing Library: Utilized for rendering components and simulating user interactions in a test DOM environment.
Jest: The test runner and mocking framework orchestrating test execution and environment isolation.
Legacy React Behavior: The tests simulate React <= 17 environments to validate SWR’s backward compatibility, impacting how SWR internally manages React's concurrent features like
startTransition.
Usage Example Summary
This file itself is a test suite, but it provides examples on how to:
Use
useSWRMutationto trigger manual mutations.Use
useSWRwith asynchronous fetchers and loading states.Properly wrap asynchronous state updates with React Testing Library’s
act()for legacy React.Dynamically load React hooks when testing isolated module environments.
Mermaid Diagram - Component Interaction Flowchart
This flowchart illustrates the interaction flow within the test cases, showing the key functions and components involved in the legacy React testing scenario.
flowchart TD
A[withLegacyReact] --> B[Dynamic import of SWR hooks]
B --> C[Page Component]
C --> D[useSWRMutation or useSWR Hook]
C --> E[Render Button or Paragraph]
E --> F[User Interaction (click)]
F --> G[trigger() or SWR fetcher]
G --> H[State update]
H --> I[UI text changes: "pending" → "data"]
I --> J[Assertions with screen queries]
style A fill:#f9f,stroke:#333,stroke-width:2px
style B fill:#bbf,stroke:#333,stroke-width:2px
style C fill:#afa,stroke:#333,stroke-width:2px
style D fill:#ffb,stroke:#333,stroke-width:2px
style E fill:#ffd,stroke:#333,stroke-width:2px
style F fill:#fbb,stroke:#333,stroke-width:2px
style G fill:#bfb,stroke:#333,stroke-width:2px
style H fill:#ddf,stroke:#333,stroke-width:2px
style I fill:#fbf,stroke:#333,stroke-width:2px
style J fill:#dfd,stroke:#333,stroke-width:2px
Summary
This test file ensures legacy React compatibility for the SWR library hooks.
It verifies that the
IS_REACT_LEGACYflag is enabled, allowing proper handling of React transitions and asynchronous updates.Tests use isolated module environments to mimic legacy React behavior.
Tests cover mutation triggering and asynchronous data fetching with
useSWRhooks.The file is critical to maintain backward compatibility and smooth user experience in older React versions.
If you need more details on the SWR library itself or integration with React 18+ features, please refer to the core SWR documentation and React concurrent mode guides.