use-swr-key.test.tsx
Overview
This file contains a comprehensive test suite for the useSWR React hook focusing on how it handles key changes. The tests ensure that useSWR correctly manages data fetching, caching, and revalidation behaviors when the cache key provided to the hook changes in various scenarios, including synchronous and asynchronous fetchers, function keys, and object keys.
The tests are written using React Testing Library and Jest, simulating component behavior and asynchronous data fetching to validate that useSWR:
Properly respects requests after the key has changed.
Returns
undefinedduring key changes when appropriate.Handles synchronous fetchers returning immediate results.
Reacts correctly when function keys change identity.
Avoids fetching when the function key throws errors.
Cleans up state when the key becomes empty.
Keeps data in sync across multiple
useSWRcalls with the same key.Supports deep comparison of object keys for caching.
This file is crucial in ensuring the robustness of useSWR's core mechanism: caching and revalidation based on keys.
Detailed Explanation of Tests and Their Components
Imports
act, fireEvent, screenfrom@testing-library/react: Utilities to simulate user events and control React component lifecycle in tests.React, useState, useEffect from
react: React core and hooks for component logic.useSWRfromswr: The hook under test.Utility functions from
./utils:createKey(): Generates unique keys for testing.createResponse(data, options): Simulates fetcher responses, optionally delayed.renderWithConfig(): Renders components with necessary configuration for SWR.sleep(ms): Utility to wait asynchronously.
Test Suite: describe('useSWR - key', () => { ... })
Each it block defines a test case verifying specific behavior related to key changes.
Test Case 1: should respect requests after key has changed
Purpose:
Verify that when the key changes, the hook respects the latest request and does not overwrite data from a slow previous request.
Implementation Details:
Component
Pageuses a key that changes based on local statemounted.When
mountedis0, fetcher returns"long request"(delay 100ms).When
mountedis1, fetcher returns"short request"(delay 50ms).The test triggers a state change that switches the key and checks that the data reflects the "short request" even after the longer "long request" finishes.
Usage:
renderWithConfig(<Page />)
await screen.findByText('data:short request')
Test Case 2: should render undefined after key has changed
Purpose:
Ensure that when the key changes, the data is reset to undefined until the new fetch completes (no stale data shown).
Implementation Details:
Key switches from
"baseKey-0"to"baseKey-1"after 200ms.Data should be
undefinedimmediately after key changes, even if previous data was present.
Test Case 3: should return undefined after key change when fetcher is synchronized
Purpose:
Test synchronous fetchers that immediately return data.
Details:
Uses a simple
samplesobject.Key changes cause data to reset to
undefinedbefore showing new fetcher result.
Test Case 4: should revalidate if a function key changes identity
Purpose:
Test that if the key is a function, SWR revalidates data when the function identity changes.
Details:
Uses a closure factory to create function keys.
When the state changes, the function key identity changes, triggering revalidation.
Test Case 5: should not fetch if the function key throws an error
Purpose:
Ensure that if the key function throws an error, no fetch occurs and data remains undefined.
Test Case 6: should cleanup state when key turns to empty
Purpose:
Verify that when the key becomes an empty string (falsy), SWR cleans up internal state and stops fetching.
Test Case 7: should keep data in sync when key updates
Purpose:
Test multiple useSWR hooks with the same key share data and stay synchronized.
Test Case 8: should support object as the key and deep compare
Purpose:
Verify SWR supports object keys and performs deep comparison to avoid redundant fetches.
Important Implementation Details and Algorithms
Key change detection:
useSWRinternally detects changes in the key (string, function, or object). This test suite validates that changes trigger cache invalidation, data reset toundefined, and revalidation.Asynchronous fetcher handling:
Tests confirm that slower fetch responses from previous keys do not overwrite newer data.Function keys:
When the cache key is a function, identity changes are treated as key changes.Deep comparison:
When keys are objects, SWR uses deep comparison to decide if keys are equal, preventing redundant fetches.Cleanup on falsy key:
When the key is falsy (empty string), SWR stops fetching and cleans up state to avoid leaks.
Interaction with Other Parts of the System
useSWRhook:
The core subject under test, providing caching and data fetching capabilities.Utility functions (
createKey,createResponse,renderWithConfig,sleep):
Provide test infrastructure and simulation of asynchronous behavior.React Testing Library:
Enables rendering React components and simulating user interactions/events.
This file ensures that the useSWR hook behaves correctly regarding cache keys, which is fundamental for its integration in upper layers of the application using SWR for data fetching.
Usage Examples from Tests
Example: Handling key changes with asynchronous fetchers
function Page() {
const [mounted, setMounted] = useState(0)
const key = `${baseKey}-${mounted ? 'short' : 'long'}`
const { data } = useSWR(key, () => {
if (mounted) {
return createResponse('short request', { delay: 50 })
}
return createResponse('long request', { delay: 100 })
})
useEffect(() => setMounted(1), [])
return <div>data:{data}</div>
}
Mermaid Diagram: Test File Workflow and Relationships
flowchart TD
A[Start Test Suite: useSWR - key]
A --> B1[Test: Respect Requests After Key Changes]
A --> B2[Test: Render Undefined After Key Change]
A --> B3[Test: Return Undefined After Key Change with Sync Fetcher]
A --> B4[Test: Revalidate on Function Key Identity Change]
A --> B5[Test: No Fetch if Function Key Throws Error]
A --> B6[Test: Cleanup State on Empty Key]
A --> B7[Test: Keep Data in Sync for Multiple Hooks]
A --> B8[Test: Support Object Keys with Deep Compare]
subgraph Components
B1 --> C1[Page component with async fetcher and state]
B2 --> C2[Page component switching keys with timeout]
B3 --> C3[Page with synchronous fetcher]
B4 --> C4[Page using function keys and closure]
B5 --> C5[Page with error-throwing key function]
B6 --> C6[Page with key becoming empty string]
B7 --> C7[Page with multiple useSWR hooks and shared key]
B8 --> C8[Page with object keys and deep comparison]
end
subgraph Utilities
C1 --> U1[createKey]
C1 --> U2[createResponse]
C1 --> U3[renderWithConfig]
C1 --> U4[sleep]
%% similar utilities used in other test components
end
subgraph React Testing Library
B1 --> RTL[act, fireEvent, screen]
B2 --> RTL
B3 --> RTL
B4 --> RTL
B5 --> RTL
B6 --> RTL
B7 --> RTL
B8 --> RTL
end
Summary
This test file verifies the core behavior of
useSWRregarding key changes, including asynchronous and synchronous fetchers, function keys, object keys, and edge cases like errors and empty keys.It is essential for ensuring that
useSWR's caching and revalidation strategies are robust and predictable.The file uses React Testing Library to simulate UI components and asynchronous data fetching.
Utility functions support generating unique keys and simulating delayed fetch responses.
The included Mermaid diagram illustrates the flow of tests, their components, and dependencies on utilities and testing tools.
This documentation should help developers understand the intent, structure, and coverage of this key-focused test suite for useSWR.