From 67abe0e470ebcbfefad7dfaa4a9835654fc1af83 Mon Sep 17 00:00:00 2001 From: Alexey Taktarov Date: Mon, 26 Feb 2024 21:51:23 +0100 Subject: [PATCH 1/4] Fixes #254. Use `flatMap()` instead of `reduce()` to flatten an array. --- packages/wouter/src/index.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/wouter/src/index.js b/packages/wouter/src/index.js index 7b030b0..3a8dd3f 100644 --- a/packages/wouter/src/index.js +++ b/packages/wouter/src/index.js @@ -220,17 +220,12 @@ export const Link = forwardRef((props, ref) => { : h("a", { ...restProps, href, onClick, children, ref }); }); -const flattenChildren = (children) => { - return Array.isArray(children) - ? [].concat( - ...children.map((c) => - c && c.type === Fragment - ? flattenChildren(c.props.children) - : flattenChildren(c) - ) +const flattenChildren = (children) => + Array.isArray(children) + ? children.flatMap((c) => + flattenChildren(c && c.type === Fragment ? c.props.children : c) ) : [children]; -}; export const Switch = ({ children, location }) => { const router = useRouter(); From 574477cdf88d908d87e6d6c85f7404d576fdc6b6 Mon Sep 17 00:00:00 2001 From: Alexey Taktarov Date: Mon, 26 Feb 2024 21:39:55 +0100 Subject: [PATCH 2/4] Extract `ssrSearch` from `ssrPath` when possible. --- packages/wouter/src/index.js | 4 +++ packages/wouter/test/router.test.tsx | 39 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/packages/wouter/src/index.js b/packages/wouter/src/index.js index 3a8dd3f..a8a41ed 100644 --- a/packages/wouter/src/index.js +++ b/packages/wouter/src/index.js @@ -116,6 +116,10 @@ export const Router = ({ children, ...props }) => { // holds to the context value: the router object let value = parent; + // when `ssrPath` contains a `?` character, we split can extract the search + const [path, search] = props.ssrPath?.split("?") ?? []; + if (search) (props.ssrSearch = search), (props.ssrPath = path); + // what is happening below: to avoid unnecessary rerenders in child components, // we ensure that the router object reference is stable, unless there are any // changes that require reload (e.g. `base` prop changes -> all components that diff --git a/packages/wouter/test/router.test.tsx b/packages/wouter/test/router.test.tsx index 6985263..fb86cf2 100644 --- a/packages/wouter/test/router.test.tsx +++ b/packages/wouter/test/router.test.tsx @@ -51,6 +51,45 @@ it("alters the current router with `parser` and `hook` options", () => { expect(router.hook).toBe(hook); }); +it("accepts `ssrPath` and `ssrSearch` params", () => { + const { result } = renderHook(() => useRouter(), { + wrapper: (props) => ( + + {props.children} + + ), + }); + + expect(result.current.ssrPath).toBe("/users"); + expect(result.current.ssrSearch).toBe("a=b&c=d"); +}); + +it("can extract `ssrSearch` from `ssrPath` after the '?' symbol", () => { + let ssrPath: string | undefined = "/no-search"; + let ssrSearch: string | undefined = undefined; + + const { result, rerender } = renderHook(() => useRouter(), { + wrapper: (props) => ( + + {props.children} + + ), + }); + + expect(result.current.ssrPath).toBe("/no-search"); + expect(result.current.ssrSearch).toBe(undefined); + + ssrPath = "/with-search?a=b&c=d"; + rerender(); + + expect(result.current.ssrPath).toBe("/with-search"); + expect(result.current.ssrSearch).toBe("a=b&c=d"); + + ssrSearch = "x=y&z=w"; + rerender(); + expect(result.current.ssrSearch).toBe("a=b&c=d"); +}); + it("shares one router instance between components", () => { const RouterGetter = ({ el }: { el: ReactElement }) => { const router = useRouter(); From 3fb98e59ab784ec778fa11bf1db9dde88f3b26b2 Mon Sep 17 00:00:00 2001 From: Alexey Taktarov Date: Sun, 3 Mar 2024 11:48:28 +0100 Subject: [PATCH 3/4] Typos and README updates. --- README.md | 9 +++++++++ packages/wouter/src/index.js | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4291cf8..7340069 100644 --- a/README.md +++ b/README.md @@ -788,6 +788,15 @@ const handleRequest = (req, res) => { }; ``` +Tip: wouter can pre-fill `ssrSearch`, if `ssrPath` contains the `?` character. So these are equivalent: + +```jsx +; + +// is the same as +; +``` + On the client, the static markup must be hydrated in order for your app to become interactive. Note that to avoid having hydration warnings, the JSX rendered on the client must match the one used by the server, so the `Router` component must be present. diff --git a/packages/wouter/src/index.js b/packages/wouter/src/index.js index a8a41ed..1739acc 100644 --- a/packages/wouter/src/index.js +++ b/packages/wouter/src/index.js @@ -116,7 +116,7 @@ export const Router = ({ children, ...props }) => { // holds to the context value: the router object let value = parent; - // when `ssrPath` contains a `?` character, we split can extract the search + // when `ssrPath` contains a `?` character, we can extract the search from it const [path, search] = props.ssrPath?.split("?") ?? []; if (search) (props.ssrSearch = search), (props.ssrPath = path); From 72b38c0d0532f1fb9808e3d7a0398b0cdfedf57b Mon Sep 17 00:00:00 2001 From: mjfwebb Date: Mon, 4 Mar 2024 21:37:30 +0100 Subject: [PATCH 4/4] feat: adds main entry to packages package.json --- packages/wouter-preact/package.json | 1 + packages/wouter/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/wouter-preact/package.json b/packages/wouter-preact/package.json index 147c5a7..c176c85 100644 --- a/packages/wouter-preact/package.json +++ b/packages/wouter-preact/package.json @@ -17,6 +17,7 @@ "types/**/*.d.ts", "types/*.d.ts" ], + "main": "esm/index.js", "exports": { ".": { "types": "./types/index.d.ts", diff --git a/packages/wouter/package.json b/packages/wouter/package.json index bd8512c..50f5327 100644 --- a/packages/wouter/package.json +++ b/packages/wouter/package.json @@ -17,6 +17,7 @@ "types/**/*.d.ts", "types/*.d.ts" ], + "main": "esm/index.js", "exports": { ".": { "types": "./types/index.d.ts",