### XRouter Integration and Navigation Examples Source: https://github.com/nfour/xroute/blob/master/README.md This snippet illustrates how to create an `XRouter` instance, define routes, and perform navigation operations. It shows how to push new routes, generate URIs, and read route parameters, including integration with `MobX` for reactive state management. It demonstrates navigating to specific routes, updating parameters in the current route, and reading route properties. ```tsx import { createHashHistory } from 'history' import { autorun, makeAutoObservable, reaction } from 'mobx' import { observer } from 'mobx-react-lite' import * as React from 'react' import { XRoute, XRouter } from 'xroute' // // Define some routes // const HomeRoute = XRoute('home') .Resource('/') // Optional language param, eg. /en or / .Type<{ pathname: {} search: { language?: 'en' | 'da' | 'de' } }>() const UserProfileRoute = HomeRoute.Extend('userProfile') .Resource('/user/:userId') // Required language, eg. /da/user/11 .Type<{ pathname: { userId: string } search: { profileSection: 'profile' | 'preferences' } }>() const router = new XRouter([UserProfileRoute, HomeRoute], createHashHistory()) export type MyXRouter = typeof router // Log some changes autorun(() => console.log('Active route:', router.route)) // Navigate to: /?language=en router.routes.home.push({ pathname: { language: 'en' } }) // Get the pathname, eg. to put inside an const homeDaUri = router.routes.home.toUri({ pathname: { language: 'da' } }) // "/da" // Navigates to: /user/11?language=en router.routes.userProfile.push({ pathname: { userId: '11' }, search: { language: 'en' }, }) // Just change the language in the active route. // This works as long as the parameter is shared between all routes. // Navigates to: /user/11?language=da router.route?.push({ pathname: { language: 'da' } }) // Re-use the current language // Navigates to: /?language=da router.routes.home.push({ search: { language: router.route?.search.language }, }) // Provide a route object to route from anywhere: // Navigate to: /de/user/55 router.push(UserProfileRoute, { pathname: { userId: '55' }, search: { language: 'de' }, }) // Read route properties: /** This must be read from the `routes.userProfile` for the type to be consistent */ router.routes.userProfile.pathname?.userId // => '55' /** Because `language` is available on all routes, we can read it from the active route at `router.route` */ router.route?.search?.language class UserProfilePage { constructor(private router: MyXRouter) { this.router = router makeAutoObservable(this) } get route() { return this.router.routes.userProfile } get userId() { ``` -------------------------------- ### Demonstrate UserProfilePage Instance Usage Source: https://github.com/nfour/xroute/blob/master/README.md Illustrates how to instantiate and interact with the `UserProfilePage` class. It shows accessing the `userId` property and updating it using the `setUserId` method, including an asynchronous delay to simulate the route update process and verify the new `userId` value. ```typescript // Play around with user profile: void (async () => { const userProfilePage = new UserProfilePage(router) userProfilePage.userId // 55 userProfilePage.setUserId('200') await new Promise((r) => setTimeout(r, 50)) // Give it time to update the URL and come back... userProfilePage.userId // 200 })() ``` -------------------------------- ### Listen to User Profile Route Activation Changes Source: https://github.com/nfour/xroute/blob/master/README.md Illustrates how to use MobX's `reaction` utility to observe changes in the `isActive` status of a specific route (e.g., `userProfile`). This pattern allows for executing side effects or logic precisely when a route becomes active or inactive, preventing redundant executions by checking `previousIsActive`. ```typescript const listenToUserProfileRoute = () => { let previousIsActive: boolean reaction( () => router.routes.userProfile.isActive, (isActive) => { if (isActive === previousIsActive) return // Ignore same state previousIsActive = isActive if (isActive) { // on enter route // ... } else { // on exit route // ... } }, ) } ``` -------------------------------- ### Define Type-Safe Routes with XRoute Source: https://github.com/nfour/xroute/blob/master/README.md This snippet demonstrates how to define various types of routes (home, admin, nested, wildcard) using `XRoute` and `Resource` for path matching, and `Type` for defining type-safe pathname and search parameters. It illustrates extending routes, handling optional parameters, and creating dynamic segments with enums. Requires MobX@6. ```tsx import { createBrowserHistory } from 'history' import { XRoute, XRouter } from 'xroute' /** A simple route, matches the `/`, the root page */ export const HomeRoute = XRoute('home') .Resource('/') // / .Type<{ pathname: {} search: {} }>() export const AdminRoute = XRoute('admin') .Resource( `/admin`, // /admin ) .Type<{ pathname: {} search: { isAdvancedView?: boolean } }>() enum AdminAnalyticsSubSections { TopPages = 'topPages', TopUsers = 'topUsers', RawData = 'rawData', } const AdminAnalyticsSubsectionsURI = `:subSection(${AdminAnalyticsSubSections.TopPages}|${AdminAnalyticsSubSections.TopUsers}|${AdminAnalyticsSubSections.RawData})?` // // OR: // if you dont care about type safety, do this: // const AdminAnalyticsSubsectionsURILoose = `:subSection(${Object.values( AdminAnalyticsSubSections, ).join('|')})?` as const export const AdminAnalyticsRoute = AdminRoute.Extend('adminAnalytics') .Resource(`/analytics/${AdminAnalyticsSubsectionsURI}`) // /admin/analytics/:subSection(topPages|topUsers|rawData) .Type<{ pathname: { subSection?: AdminAnalyticsSubSections } search: {} }>() export const AdminUsersRoute = AdminRoute.Extend('adminUsers') .Resource(`/users`) // /admin/users .Type<{ pathname: {} // You don't need to use the pathname at all if you want to keep it simple // Can even nest objects and arrays. search: { userId?: string // ends up as ?userId=123 editor?: { line?: string activeToolId?: string selectedItems?: string[] } // ?editor[line]=1&editor[activeToolId]=2&editor[selectedItems]=3&editor[selectedItems]=4 } }>() export const NotFoundRoute = XRoute('notFound') .Resource('/:someGarbage(.*)?') // /:someGarbage(.*)? .Type<{ pathname: { /** The pathname that didnt match any route */ someGarbage?: string } search: {} }>() export function createRouter() { return new XRouter( // Order matters, notice the `notFound` route is at the end, to act as a fallback [ AdminAnalyticsRoute, // /admin/analytics/topPages AdminUsersRoute, // /admin/users?userId=123&editor[line]=1&editor[activeToolId]=2&editor[selectedItems]=3&editor[selectedItems]=4 AdminRoute, // /admin HomeRoute, // / NotFoundRoute // /asdaskjdkalsdjklasd ], createBrowserHistory(), ) } ``` -------------------------------- ### Import XRouteSchema to Resolve TypeScript Errors Source: https://github.com/nfour/xroute/blob/master/README.md Offers alternative import statements to resolve TypeScript type inference issues, particularly when the project uses `zod` for schema generation. Importing `xroute/XRouteSchema` or its older path `xroute/x/esm/XRouteSchema` can help TypeScript correctly infer types. ```typescript import 'xroute/XRouteSchema' // or if that doesnt work in your older typescript project, use the ugly path: import 'xroute/x/esm/XRouteSchema' ``` -------------------------------- ### Define UserProfilePage Class for Route Interaction Source: https://github.com/nfour/xroute/blob/master/README.md Defines a `UserProfilePage` class that encapsulates route-related logic for user profiles. It demonstrates how to access `userId` and `profileSection` from the current route's `pathname` and `search` properties, and how to update these parameters using `this.route.push` and `this.route.pushExact` for flexible route manipulation. ```typescript return this.route.pathname?.userId } get profileSection() { return this.route.search?.profileSection } setUserId(userId: string) { // Uses current route params this.route.push({ pathname: { userId } }) // // or // // Explicitly use previous params... this.route.pushExact((uri) => ({ ...uri, pathname: { ...uri.pathname, userId }, })) } setProfileSection(profileSection: this['profileSection']) { this.route.push({ search: { profileSection } }) // sets ?profileSection="" } ``` -------------------------------- ### Integrate XRouter with React Component Source: https://github.com/nfour/xroute/blob/master/README.md Demonstrates how to integrate `XRouter` within a React functional component using `React.useState` and `observer`. It shows initializing `XRouter` with defined routes and a history mechanism, then conditionally rendering UI elements based on the active route's `key` or `isActive` status, and accessing route parameters like `userId` and `language`. ```typescript const Component = observer(() => { const [router] = React.useState( () => new XRouter([UserProfileRoute, HomeRoute], createHashHistory()), ) return ( <> {router.route?.key === 'home' &&
Home Page!
} { // Or do this: } {router.routes.userProfile.isActive && (
User Profile! UserID: {router.routes.userProfile.pathname?.userId}
)} ) }) ``` -------------------------------- ### Resolve TypeScript Module Resolution Errors with tsconfig Source: https://github.com/nfour/xroute/blob/master/README.md Provides a `tsconfig.json` configuration snippet to address common TypeScript errors like 'The inferred type of "X" cannot be named without a reference to "Y"', which can occur when using libraries like `zod` for schema generation. Updating `moduleResolution` and `module` to `NodeNext` can help resolve these issues. ```json { "compilerOptions": { "moduleResolution": "NodeNext", "module": "NodeNext" } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.