@aminnairi/react-router 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +64 -0
  2. package/index.tsx +38 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -735,6 +735,40 @@ createPage({
735
735
  });
736
736
  ```
737
737
 
738
+ ### useLink
739
+
740
+ Allow you to navigate to another page using a JSX component instead of a callback as for the `useNavigateToPage` hook.
741
+
742
+ The created component is simply a `<a href="...">{children}</a>` under the hood which prevents the default behavior of the navigator which is to create a new HTTP request and to reload the page. The `href` attribute is computed from the page path and its parameters.
743
+
744
+ ```tsx
745
+ import { Fragment } from "react";
746
+ import { createPage, useLink } from "@aminnairi/react-router";
747
+
748
+ const user = createPath({
749
+ path: "/users/:user",
750
+ element: function User({ parameters: { user }}) {
751
+ return (
752
+ <h1>User#{user}</h1>
753
+ );
754
+ }
755
+ });
756
+
757
+ createPage({
758
+ path: "/about",
759
+ element: function About() {
760
+ const Link = useLink(user);
761
+
762
+ return (
763
+ <Fragment>
764
+ <h1>About</h1>
765
+ <Link parameters={{ user: "123" }}>User#123</Link>
766
+ </Fragment>
767
+ );
768
+ }
769
+ });
770
+ ```
771
+
738
772
  ### useSearch
739
773
 
740
774
  Allow you to get one or more search query from the URL.
@@ -976,10 +1010,40 @@ See [`LICENSE`](./LICENSE).
976
1010
 
977
1011
  ### Versions
978
1012
 
1013
+ - [`1.1.0`](#110)
1014
+ - [`1.0.1`](#101)
979
1015
  - [`1.0.0`](#100)
980
1016
  - [`0.1.1`](#011)
981
1017
  - [`0.1.0`](#010)
982
1018
 
1019
+ ### 1.1.0
1020
+
1021
+ #### Major changes
1022
+
1023
+ None.
1024
+
1025
+ #### Minor changes
1026
+
1027
+ - Added a new `useLink` hook to create components that allow for navigating to another page
1028
+
1029
+ #### Bug & security fixes
1030
+
1031
+ None.
1032
+
1033
+ ### 1.0.1
1034
+
1035
+ #### Major changes
1036
+
1037
+ None.
1038
+
1039
+ #### Minor changes
1040
+
1041
+ None.
1042
+
1043
+ #### Bug & security fixes
1044
+
1045
+ - Fixed an issue when navigating to a page that already starts with a slash
1046
+
983
1047
  ### 1.0.0
984
1048
 
985
1049
  #### Major changes
package/index.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useEffect, useState, FunctionComponent, useMemo, Component, PropsWithChildren, createContext, SetStateAction, Dispatch, ReactNode, useContext } from "react";
1
+ import { useEffect, useState, FunctionComponent, useMemo, Component, PropsWithChildren, createContext, SetStateAction, Dispatch, ReactNode, useContext, useCallback, memo, MouseEvent } from "react";
2
2
 
3
3
  export type AbsolutePath<Path extends string> =
4
4
  Path extends `${infer Start}:${string}/${infer Rest}`
@@ -39,11 +39,11 @@ export interface FindPageOptions {
39
39
  }
40
40
 
41
41
  export const sanitizePath = (path: string): string => {
42
- return "/" + path
43
- .replace(/^\/|\/$/g, "")
44
- .replace(/\/+/g, "/");
42
+ const sanitizedPath = path.replace(/\/+/g, "/").replace(/^\/|\/$/g, "")
43
+ return "/" + sanitizedPath;
45
44
  }
46
45
 
46
+
47
47
  export const createPage = <Path extends string>(page: Page<Path>) => {
48
48
  return page
49
49
  }
@@ -180,10 +180,12 @@ const Context = createContext<ContextInterface>({
180
180
  export const useNavigateToPage = <Path extends string>(page: Page<Path>) => {
181
181
  const { prefix } = useContext(Context);
182
182
 
183
- return (parameters: Parameters<Path>, replace: boolean = false) => {
183
+ return useCallback((parameters: Parameters<Path>, replace: boolean = false) => {
184
+ const initialPath = sanitizePath(`${prefix ?? ""}/${page.path}`);
185
+
184
186
  const pathWithParameters = Object.entries(parameters).reduce((path, [parameterName, parameterValue]) => {
185
187
  return path.replace(`:${parameterName}`, parameterValue);
186
- }, sanitizePath(`${prefix ?? ""}/${page.path}`));
188
+ }, initialPath);
187
189
 
188
190
  if (replace) {
189
191
  window.history.replaceState(null, pathWithParameters, pathWithParameters);
@@ -192,7 +194,7 @@ export const useNavigateToPage = <Path extends string>(page: Page<Path>) => {
192
194
  }
193
195
 
194
196
  window.dispatchEvent(new CustomEvent("popstate"));
195
- }
197
+ }, [page]);
196
198
  };
197
199
 
198
200
  export const useIsActivePage = (page: Page<string>) => {
@@ -212,6 +214,35 @@ export const useHash = () => {
212
214
  return hash;
213
215
  };
214
216
 
217
+ export const useLink = <Path extends string>(page: Page<Path>) => {
218
+ const Link = memo(({ children, parameters }: { children: ReactNode, parameters: Parameters<Path> }) => {
219
+ const { prefix } = useContext(Context);
220
+ const navigateToPage = useNavigateToPage(page);
221
+
222
+ const pathWithParameters = useMemo(() => {
223
+ return Object.entries(parameters).reduce((previousPath, [parameterName, parameterValue]) => {
224
+ return previousPath.replace(`:${parameterName}`, parameterValue);
225
+ }, sanitizePath(`${prefix ?? ""}/${page.path}`));
226
+ }, []);
227
+
228
+ const navigate = useCallback((event: MouseEvent) => {
229
+ event.preventDefault();
230
+ navigateToPage(parameters);
231
+ }, []);
232
+
233
+ return (
234
+ <a
235
+ href={pathWithParameters}
236
+ onClick={navigate}>
237
+ {children}
238
+ </a>
239
+ );
240
+
241
+ });
242
+
243
+ return Link;
244
+ };
245
+
215
246
  export const createRouter = <Path extends string>({ pages, fallback, transition: withViewTransition, issue, prefix }: CreateRouterOptions<Path>) => {
216
247
  const Provider = ({ children }: ProviderProps) => {
217
248
  const [pathname, setPathname] = useState(sanitizePath(window.location.pathname));
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "name": "@aminnairi/react-router",
4
4
  "description": "Type-safe router for the React library",
5
- "version": "1.0.0",
5
+ "version": "1.1.0",
6
6
  "homepage": "https://github.com/aminnairi/react-router#readme",
7
7
  "license": "MIT",
8
8
  "bugs": {