@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.
- package/README.md +64 -0
- package/index.tsx +38 -7
- 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
|
-
|
|
43
|
-
|
|
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
|
-
},
|
|
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