Skip to content

Commit ce66934

Browse files
committed
fix: address PR review comments on stack best practice skills
- Fix flutter State class widget property initialization - Add serverless caveat to rate-limiting example - Add missing nested Pydantic models in FastAPI patterns - Add missing imports and fix pagination robustness - Add concrete GOOD example for widget rebuild pattern - Add EmptyOrderError to clean architecture error hierarchy - Fix useResilientFetch hook example with refetch callback
1 parent e17d9dc commit ce66934

6 files changed

Lines changed: 75 additions & 9 deletions

File tree

skills/fastapi-endpoint-patterns/SKILL.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,25 @@ class AddressRequest(BaseModel):
7676
state: str = Field(min_length=2, max_length=2)
7777
zip_code: str = Field(pattern=r"^\d{5}(-\d{4})?$")
7878

79+
class OrderItemRequest(BaseModel):
80+
product_id: int
81+
quantity: int = Field(ge=1)
82+
notes: str | None = None
83+
7984
class CreateOrderRequest(BaseModel):
8085
items: list[OrderItemRequest] = Field(min_length=1)
8186
shipping_address: AddressRequest
8287
notes: str | None = None
8388

89+
class OrderItemResponse(BaseModel):
90+
id: int
91+
product_id: int
92+
quantity: int
93+
unit_price: float
94+
subtotal: float
95+
96+
model_config = {"from_attributes": True}
97+
8498
class OrderResponse(BaseModel):
8599
id: int
86100
status: OrderStatus
@@ -324,6 +338,11 @@ async def create_user(
324338

325339
```python
326340
from pydantic import BaseModel, Field
341+
from typing import Generic, TypeVar
342+
import math
343+
from sqlalchemy import func, select
344+
345+
T = TypeVar("T")
327346

328347
class PaginationParams(BaseModel):
329348
page: int = Field(1, ge=1)
@@ -345,7 +364,7 @@ async def list_users(
345364
pagination: PaginationParams = Depends(),
346365
db: AsyncSession = Depends(get_db),
347366
):
348-
total = await db.scalar(select(func.count(User.id)))
367+
total = await db.scalar(select(func.count(User.id))) or 0
349368
result = await db.execute(
350369
select(User)
351370
.offset(pagination.offset)
@@ -359,7 +378,7 @@ async def list_users(
359378
total=total,
360379
page=pagination.page,
361380
size=pagination.size,
362-
pages=math.ceil(total / pagination.size),
381+
pages=math.ceil(total / pagination.size) if pagination.size > 0 else 0,
363382
)
364383
```
365384

skills/flutter-state-management/SKILL.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,15 @@ class LikeButton extends StatefulWidget {
4747
}
4848
4949
class _LikeButtonState extends State<LikeButton> {
50-
late int _count = widget.initialCount;
50+
late int _count;
5151
bool _isLiked = false;
5252
53+
@override
54+
void initState() {
55+
super.initState();
56+
_count = widget.initialCount;
57+
}
58+
5359
void _toggleLike() {
5460
setState(() {
5561
_isLiked = !_isLiked;

skills/flutter-widget-patterns/SKILL.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,38 @@ class _MyState extends State<MyWidget> {
395395
}
396396
}
397397
398-
// GOOD: Extract counter into its own widget
399-
// ExpensiveHeader and ExpensiveFooter are const and skip rebuilds
398+
// GOOD: Extract the changing part into its own widget
399+
class MyWidget extends StatelessWidget {
400+
const MyWidget({super.key});
401+
402+
@override
403+
Widget build(BuildContext context) {
404+
return Column(
405+
children: [
406+
const ExpensiveHeader(), // Never rebuilds
407+
const CounterText(), // Only this rebuilds
408+
const ExpensiveFooter(), // Never rebuilds
409+
],
410+
);
411+
}
412+
}
413+
414+
class CounterText extends StatefulWidget {
415+
const CounterText({super.key});
416+
417+
@override
418+
State<CounterText> createState() => _CounterTextState();
419+
}
420+
421+
class _CounterTextState extends State<CounterText> {
422+
int _counter = 0;
423+
424+
@override
425+
Widget build(BuildContext context) {
426+
return GestureDetector(
427+
onTap: () => setState(() => _counter++),
428+
child: Text('$_counter'),
429+
);
430+
}
431+
}
400432
```

skills/nextjs-api-patterns/SKILL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ export async function updateProfile(formData: FormData) {
359359

360360
## Rate Limiting
361361

362+
> **Note:** The in-memory example below is for demonstration only. In serverless or distributed environments (e.g., Vercel), the `Map` resets with each function invocation. For production, use Redis, Upstash, or a similar persistent store.
363+
362364
```tsx
363365
// lib/rate-limit.ts
364366
const rateLimit = new Map<string, { count: number; resetTime: number }>();

skills/python-clean-architecture/SKILL.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ class InactiveUserError(DomainError):
331331
class OrderNotEditableError(DomainError):
332332
def __init__(self, order_id: str, status: str):
333333
super().__init__(f"Order {order_id} cannot be edited in status '{status}'")
334+
335+
class EmptyOrderError(DomainError):
336+
def __init__(self, order_id: str):
337+
super().__init__(f"Order {order_id} cannot be submitted with no items")
334338
```
335339

336340
### Mapping Domain Errors to HTTP

skills/react-hook-patterns/SKILL.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,17 +319,20 @@ function useOnlineStatus() {
319319
// Composed hook
320320
function useResilientFetch<T>(url: string) {
321321
const isOnline = useOnlineStatus();
322-
const result = useFetch<T>(isOnline ? url : null);
322+
const [fetchKey, setFetchKey] = useState(0);
323+
const result = useFetch<T>(isOnline ? url : null, fetchKey);
323324
const debouncedRetry = useDebounce(isOnline, 2000);
324325

326+
const refetch = useCallback(() => setFetchKey((k) => k + 1), []);
327+
325328
// Auto-retry when coming back online (debounced)
326329
useEffect(() => {
327330
if (debouncedRetry && result.status === "error") {
328-
// trigger refetch by remounting
331+
refetch();
329332
}
330-
}, [debouncedRetry, result.status]);
333+
}, [debouncedRetry, result.status, refetch]);
331334

332-
return { ...result, isOnline };
335+
return { ...result, isOnline, refetch };
333336
}
334337
```
335338

0 commit comments

Comments
 (0)