Skip to content

Commit cde9cd5

Browse files
authored
Suspense Query to Suspense Queries Example (#9)
* . * . * guide * readme * . * done * readme format
1 parent a6c9ab7 commit cde9cd5

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Transform useSuspenseQuery to useSuspenseQueries
2+
3+
This example demonstrates how to use Codegen to automatically convert multiple `useSuspenseQuery` calls to a single `useSuspenseQueries` call in React codebases. The migration script makes this process simple by handling all the tedious manual updates automatically.
4+
5+
## How the Migration Script Works
6+
7+
The script automates the entire migration process in a few key steps:
8+
9+
1. **File Detection**
10+
```python
11+
for file in codebase.files:
12+
if "useSuspenseQuery" not in file.source:
13+
continue
14+
```
15+
- Automatically identifies files using `useSuspenseQuery`
16+
- Skips irrelevant files to avoid unnecessary processing
17+
- Uses Codegen's intelligent code analysis engine
18+
19+
2. **Import Management**
20+
```python
21+
import_str = "import { useQuery, useSuspenseQueries } from '@tanstack/react-query'"
22+
file.add_import_from_import_string(import_str)
23+
```
24+
- Uses Codegen's import analysis to add required imports
25+
- Preserves existing import structure
26+
- Handles import deduplication automatically
27+
28+
3. **Query Transformation**
29+
```python
30+
# Convert multiple queries to single useSuspenseQueries call
31+
new_query = f"const [{', '.join(results)}] = useSuspenseQueries({{queries: [{', '.join(queries)}]}})"
32+
```
33+
- Collects multiple `useSuspenseQuery` calls
34+
- Combines them into a single `useSuspenseQueries` call
35+
- Maintains variable naming and query configurations
36+
37+
## Why This Makes Migration Easy
38+
39+
1. **Zero Manual Updates**
40+
- Codegen SDK handles all the file searching and updating
41+
- No tedious copy-paste work
42+
43+
2. **Consistent Changes**
44+
- Ensures all transformations follow the same patterns
45+
- Maintains code style consistency
46+
47+
3. **Safe Transformations**
48+
- Validates changes before applying them
49+
- Easy to review and revert if needed
50+
51+
## Common Migration Patterns
52+
53+
### Multiple Query Calls
54+
```typescript
55+
// Before
56+
const result1 = useSuspenseQuery(queryConfig1)
57+
const result2 = useSuspenseQuery(queryConfig2)
58+
const result3 = useSuspenseQuery(queryConfig3)
59+
60+
// Automatically converted to:
61+
const [result1, result2, result3] = useSuspenseQueries({
62+
queries: [queryConfig1, queryConfig2, queryConfig3]
63+
})
64+
```
65+
66+
## Key Benefits to Note
67+
68+
1. **Reduced Re-renders**
69+
- Single query call instead of multiple separate calls
70+
- Better React performance
71+
72+
2. **Improved Code Readability**
73+
- Cleaner, more consolidated query logic
74+
- Easier to maintain and understand
75+
76+
3. **Network Optimization**
77+
- Batched query requests
78+
- Better resource utilization
79+
80+
## Running the Migration
81+
82+
```bash
83+
# Install Codegen
84+
pip install codegen
85+
86+
# Run the migration
87+
python run.py
88+
```
89+
90+
The script will:
91+
1. Initialize the codebase
92+
2. Find files containing `useSuspenseQuery`
93+
3. Apply the transformations
94+
4. Print detailed progress information
95+
96+
## Learn More
97+
98+
- [React Query Documentation](https://tanstack.com/query/latest)
99+
- [useSuspenseQueries API](https://tanstack.com/query/latest/docs/react/reference/useSuspenseQueries)
100+
- [Codegen Documentation](https://docs.codegen.com)
101+
102+
## Contributing
103+
104+
Feel free to submit issues and enhancement requests!
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import codegen
2+
from codegen import Codebase
3+
from codegen.sdk.core.detached_symbols.function_call import FunctionCall
4+
5+
6+
@codegen.function("useSuspenseQuery-to-useSuspenseQueries")
7+
def run(codebase: Codebase):
8+
"""Convert useSuspenseQuery calls to useSuspenseQueries in a React codebase.
9+
10+
This codemod:
11+
1. Finds all files containing useSuspenseQuery
12+
2. Adds the necessary import statement
13+
3. Converts multiple useSuspenseQuery calls to a single useSuspenseQueries call
14+
"""
15+
# Import statement for useSuspenseQueries
16+
import_str = "import { useQuery, useSuspenseQueries } from '@tanstack/react-query'"
17+
18+
# Track statistics
19+
files_modified = 0
20+
functions_modified = 0
21+
22+
# Iterate through all files in the codebase
23+
for file in codebase.files:
24+
if "useSuspenseQuery" not in file.source:
25+
continue
26+
27+
print(f"Processing {file.filepath}")
28+
# Add the import statement
29+
file.add_import_from_import_string(import_str)
30+
file_modified = False
31+
32+
# Iterate through all functions in the file
33+
for function in file.functions:
34+
if "useSuspenseQuery" not in function.source:
35+
continue
36+
37+
results = [] # Store left-hand side of assignments
38+
queries = [] # Store query arguments
39+
old_statements = [] # Track statements to replace
40+
41+
# Find useSuspenseQuery assignments
42+
for stmt in function.code_block.assignment_statements:
43+
if not isinstance(stmt.right, FunctionCall):
44+
continue
45+
46+
fcall = stmt.right
47+
if fcall.name != "useSuspenseQuery":
48+
continue
49+
50+
old_statements.append(stmt)
51+
results.append(stmt.left.source)
52+
queries.append(fcall.args[0].value.source)
53+
54+
# Convert to useSuspenseQueries if needed
55+
if old_statements:
56+
new_query = f"const [{', '.join(results)}] = useSuspenseQueries({{queries: [{', '.join(queries)}]}})"
57+
print(
58+
f"Converting useSuspenseQuery to useSuspenseQueries in {function.name}"
59+
)
60+
61+
# Print the diff
62+
print("\nOriginal code:")
63+
print("\n".join(stmt.source for stmt in old_statements))
64+
print("\nNew code:")
65+
print(new_query)
66+
print("-" * 50)
67+
68+
# Replace old statements with new query
69+
for stmt in old_statements:
70+
stmt.edit(new_query)
71+
72+
functions_modified += 1
73+
file_modified = True
74+
75+
if file_modified:
76+
files_modified += 1
77+
78+
print("\nModification complete:")
79+
print(f"Files modified: {files_modified}")
80+
print(f"Functions modified: {functions_modified}")
81+
82+
83+
if __name__ == "__main__":
84+
print("Initializing codebase...")
85+
codebase = Codebase.from_repo("deepfence/ThreatMapper")
86+
87+
print("Running codemod...")
88+
run(codebase)

0 commit comments

Comments
 (0)