Skip to content

Commit

Permalink
Accept queryParams and hash in URL
Browse files Browse the repository at this point in the history
  • Loading branch information
willybrauner committed Oct 4, 2023
1 parent daea764 commit 8b412e4
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 21 deletions.
2 changes: 1 addition & 1 deletion examples/example-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"build": "vite build"
},
"dependencies": {
"@cher-ami/router": "^3.0.0-beta.5",
"@cher-ami/router": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 8 additions & 16 deletions src/components/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import debug from "@wbe/debug";
import { BrowserHistory, HashHistory, MemoryHistory } from "history";
import { Match } from "path-to-regexp";
import React, { useMemo } from "react";
import { formatRoutes } from "../core/core";
import {extractQueryParamsAndHash, formatRoutes} from "../core/core"
import { getNotFoundRoute, getRouteFromUrl } from "../core/core";
import { Routers } from "../core/Routers";
import LangService, { TLanguage } from "../core/LangService";
Expand Down Expand Up @@ -232,21 +232,14 @@ function Router(props: {
* Dispatch new routes via RouterContext
*/

const handleHistory = async (url: string = "", hash: string = ""): Promise<void> => {
// because we can get #" in hash history context, we need define current URL
// as the URL part after the "#"
let exactUrl: string = url;
if (hash?.length > 0) {
exactUrl = hash.replace("#", "");
}

const handleHistory = async (url = ""): Promise<void> => {
if (_paused.current) {
_waitingUrl.current = exactUrl;
_waitingUrl.current = url;
return;
}

const matchingRoute = getRouteFromUrl({
pUrl: exactUrl,
pUrl: url,
pRoutes: routes,
pBase: props.base,
id: props.id,
Expand All @@ -272,12 +265,11 @@ function Router(props: {
if (!newRoute) return;
// store cache
const cache = staticPropsCache();
// check if new route data as been store in cache


// check if new route data as been store in cache
// the matcher will match even if the URL ends with a slash,
// so we need to remove it to get the right cache key
const cacheKey = newRoute._fullUrl.endsWith("/")
const cacheKey = newRoute._fullUrl?.endsWith("/")
? removeLastCharFromString(newRoute._fullUrl, "/")
: newRoute._fullUrl

Expand Down Expand Up @@ -357,9 +349,9 @@ function Router(props: {
return;
// client
} else if (history) {
handleHistory(window.location.pathname, window.location.hash);
handleHistory(window.location.pathname + window.location.search + window.location.hash);
return history?.listen(({ location }) => {
handleHistory(location.pathname, location.hash);
handleHistory(location.pathname + location.search + location.hash);
});
// log error
} else {
Expand Down
48 changes: 45 additions & 3 deletions src/core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ type TGetRouteFromUrl = {
pMatcher?: any;
pParent?: TRoute;
id?: number | string;
urlWithoutHashAndQuery?: string
};

/**
Expand All @@ -249,23 +250,28 @@ export function getRouteFromUrl({
}: TGetRouteFromUrl): TRoute {
if (!pRoutes || pRoutes?.length === 0) return;

// extract query params and hash
const {queryParams, hash, urlWithoutHashAndQuery} = extractQueryParamsAndHash(pUrl)

function next({
pUrl,
urlWithoutHashAndQuery,
pRoutes,
pBase,
pMatcher,
pParent,
id,
}: TGetRouteFromUrl): TRoute {

// test each routes
for (let currentRoute of pRoutes) {
// create parser & matcher
const currentRoutePath = removeLastCharFromString(
joinPaths([pBase, currentRoute.path as string]),
"/"
);
const matcher = match(currentRoutePath)(pUrl);
log(id, `"${pUrl}" match with "${currentRoutePath}"?`, !!matcher);
const matcher = match(currentRoutePath)(urlWithoutHashAndQuery);
log(id, `"${urlWithoutHashAndQuery}" match with "${currentRoutePath}"?`, !!matcher);

// if current route path match with the param url
if (matcher) {
Expand All @@ -282,6 +288,8 @@ export function getRouteFromUrl({
parser: pMatcher || matcher,
name: route?.name || route?.component?.displayName,
getStaticProps: route?.getStaticProps,
queryParams,
hash,
props: {
params,
...(route?.props || {}),
Expand All @@ -307,6 +315,7 @@ export function getRouteFromUrl({
// else, call recursively this same method with new params
const matchingChildren = next({
pUrl,
urlWithoutHashAndQuery,
id,
pRoutes: currentRoute?.children,
pParent: pParent || currentRoute,
Expand All @@ -322,7 +331,7 @@ export function getRouteFromUrl({
}
}

return next({ pUrl, pRoutes, pBase, pMatcher, id });
return next({ pUrl, urlWithoutHashAndQuery, pRoutes, pBase, pMatcher, id });
}

/**
Expand All @@ -336,6 +345,39 @@ export function getNotFoundRoute(routes: TRoute[]): TRoute {
);
}


export const extractQueryParamsAndHash = (url: string): {
queryParams: {[x:string]: string},
hash:string,
urlWithoutHashAndQuery :string
} => {
let queryParams = {}
let hash = null
const queryIndex = url.indexOf("?")
const hashIndex = url.indexOf("#")

if (queryIndex === -1 && hashIndex === -1) {
console.log('passs icicici')
return {queryParams, hash, urlWithoutHashAndQuery: url}
}

// Extract hash
if (hashIndex !== -1) {
hash = url.slice(hashIndex + 1)
}
// Extract query parameters
if (queryIndex !== -1) {
const queryString = url.slice(queryIndex + 1, hashIndex !== -1 ? hashIndex : undefined)
const searchParams = new URLSearchParams(queryString)
searchParams.forEach((value, key) => (queryParams[key] = value))
}
// finally remove query and hash from pathname
for (let e of ["?", "#"]) {
url = url.includes(e) ? url.split(e)[0] : url
}
return { queryParams, hash, urlWithoutHashAndQuery: url}
}

// ----------------------------------------------------------------------------- ROUTES

/**
Expand Down

0 comments on commit 8b412e4

Please sign in to comment.