Skip to content

Conversation

@DJanocha
Copy link

@DJanocha DJanocha commented Jul 13, 2025

Add URL Search Parameter State Management

🚀 Summary

This PR adds comprehensive URL search parameter state management to declarative-routing, making it as easy to work with URL parameters as React state. The main addition is the useSearchParamsState hook that provides automatic synchronization, debouncing, and type safety.

✨ New Features

1. useSearchParamsState Hook

  • React state-like interface for URL search parameters
  • Built-in debouncing for real-time inputs
  • Automatic URL synchronization
  • Type-safe with Zod validation
const {
  searchParams,
  setSearchParams,
  debouncedSetSearchParams,
  resetAllValues,
} = useSearchParamsState(routeBuilder);

2. Enhanced useParams with Partial Support

  • Added {partial: true} option for conditional parameter parsing
  • Prevents errors in layouts when parameters might not be present
  • Enhanced error messages with helpful hints

3. Advanced Debouncing System

  • New useDebounceCallback hook with throttle support
  • Configurable delay, leading/trailing options
  • Proper cleanup and control methods

4. Improved URL Parameter Handling

  • Type-aware array parameter parsing
  • Better handling of optional and nullable parameters
  • Consistent behavior across all parameter types

5. Exposed urlBuilder for API Routes

  • All route builders now expose their urlBuilder function
  • Enables getting API route URLs without making actual HTTP calls
  • Perfect for external service integrations and webhook configurations
// File uploads with Vercel Blob
const handleUploadUrl = postApiUploadType.urlBuilder(
  { type: uploadTypeMatchingFile },
  { allowOverwrite },
);

// Direct usage with Next.js Link (alternative to routeBuilder.Link)
<Link href={routeBuilder.urlBuilder(params, searchParams)}>Custom Link</Link>;

// Webhook URLs for auth providers (OAuth callbacks)
const callbackUrl = authCallbackRoute.urlBuilder({ provider: "google" });
await configureGoogleOAuth({
  redirectUri: `${process.env.APP_URL}${callbackUrl}`,
});

// Configure webhook URLs for external services
const webhookRoute = myWebhookRoute.urlBuilder();
const fullWebhookUrl = `${process.env.APP_URL}${webhookRoute}`;
// Use fullWebhookUrl when configuring webhooks in Stripe Dashboard
// or when registering webhook endpoints programmatically

🔧 Technical Changes

  • Type System: Changed from ZodSchema to ZodAnyObject for better .partial() support
  • URL Generation: Fixed missing leading slash in generated URLs
  • Dependencies: Added lodash.debounce and lodash.throttle with types
  • Build: Added build:watch script for development

📚 Documentation & Examples

  • Comprehensive example: examples/nextjs/with-use-search-params-state/
  • Detailed documentation: FEATURES.md
  • Real-world usage: Pokemon app demonstrating search, filtering, pagination, and navigation

🔄 Breaking Changes

None - All existing code continues to work unchanged. New features are opt-in.

📦 Migration Guide

For existing users:

No migration needed - all existing code continues to work unchanged.

New features you can adopt:

// New: URL search parameter state management
const { searchParams, setSearchParams, debouncedSetSearchParams } =
  useSearchParamsState(routeBuilder);

// New: Partial params in layouts
const params = useParams(routeBuilder, { partial: true });

// New: Get API route URLs without calling them
const uploadUrl = apiRouteBuilder.urlBuilder(params, searchParams);

🎯 Use Cases

This enhancement is perfect for:

  • Search interfaces with real-time filtering
  • Data tables with pagination and sorting
  • Form state persistence in URLs
  • Dashboard filters that survive page refreshes
  • Multi-step wizards with URL state
  • File upload services that require API endpoint URLs
  • External integrations needing route URLs without HTTP calls

📋 Checklist

  • New functionality is documented
  • Example application demonstrates all features
  • Type definitions are updated
  • No breaking changes introduced
  • Build scripts updated
  • urlBuilder exposed on all route builders

@DJanocha DJanocha force-pushed the use-search-params-state branch from c42c1ed to a41c83f Compare July 13, 2025 14:18
@DJanocha
Copy link
Author

Hi @jherr ! 👋

Just wanted to give this a gentle ping when you have a moment to review.

Key additions:
• Exposed urlBuilder for external services (Vercel Blob, etc.)
• New useSearchParamsState hook with debouncing
• Enhanced useParams with partial support
• **Resolves #45 ** - fixes missing leading slash in generated URLs

No breaking changes - all existing code continues to work. Thanks for your time! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant