From 609cc5e1ba8abd3dd0ed7649bbaca60fe4a4976e Mon Sep 17 00:00:00 2001 From: GravityTwoG <crytekov@gmail.com> Date: Wed, 3 Jul 2024 21:50:48 +0700 Subject: [PATCH] revert previous changes and modify navigate to resolve destinations like "/abc?def" to "?def#/abc" --- packages/wouter/src/use-hash-location.js | 49 ++++++------------- .../wouter/test/use-hash-location.test.tsx | 23 +-------- .../wouter/types/use-browser-location.d.ts | 9 +--- packages/wouter/types/use-hash-location.d.ts | 8 --- 4 files changed, 16 insertions(+), 73 deletions(-) diff --git a/packages/wouter/src/use-hash-location.js b/packages/wouter/src/use-hash-location.js index eef59b5..35d3171 100644 --- a/packages/wouter/src/use-hash-location.js +++ b/packages/wouter/src/use-hash-location.js @@ -19,52 +19,31 @@ const subscribeToHashUpdates = (callback) => { }; }; -export const useLocationProperty = (fn, ssrFn) => - useSyncExternalStore(subscribeToHashUpdates, fn, ssrFn); - -// when useHashLocation is used, location.search is always empty -// so we must retrieve string from the hash -const currentSearch = () => { - const hash = location.hash; - const hashLocation = "/" + hash.replace(/^#?\/?/, ""); - - const questionMarkIdx = hashLocation.indexOf("?"); - if (questionMarkIdx !== -1) { - return hashLocation.slice(questionMarkIdx + 1, hashLocation.length); - } - - return ""; -}; - -export const useSearch = ({ ssrSearch = "" } = {}) => - useLocationProperty(currentSearch, () => ssrSearch); - // leading '#' is ignored, leading '/' is optional -const currentHashLocation = () => { - const hash = location.hash; - const hashLocation = "/" + hash.replace(/^#?\/?/, ""); - - // remove query string - const questionMarkIdx = hashLocation.indexOf("?"); - if (questionMarkIdx !== -1) { - return hashLocation.slice(0, questionMarkIdx); - } - - return hashLocation; -}; +const currentHashLocation = () => "/" + location.hash.replace(/^#?\/?/, ""); export const navigate = (to, { state = null } = {}) => { // calling `replaceState` allows us to set the history // state without creating an extra entry + + let hash = to.replace(/^#?\/?/, ""); + let search = location.search; + + const searchIdx = hash.indexOf("?"); + if (searchIdx !== -1) { + search = hash.slice(searchIdx, hash.length); + hash = hash.slice(0, searchIdx); + } + history.replaceState( state, "", - // keep the current pathname, current query string, but replace the hash + // keep the current pathname, but replace query string and hash location.pathname + - location.search + + search + // update location hash, this will cause `hashchange` event to fire // normalise the value before updating, so it's always preceeded with "#/" - (location.hash = `#/${to.replace(/^#?\/?/, "")}`) + (location.hash = `#/${hash}`) ); }; diff --git a/packages/wouter/test/use-hash-location.test.tsx b/packages/wouter/test/use-hash-location.test.tsx index 8da8052..77b2b0a 100644 --- a/packages/wouter/test/use-hash-location.test.tsx +++ b/packages/wouter/test/use-hash-location.test.tsx @@ -3,7 +3,7 @@ import { renderHook, render } from "@testing-library/react"; import { renderToStaticMarkup } from "react-dom/server"; import { Router, Route, useLocation, Link } from "wouter"; -import { useHashLocation, useSearch } from "wouter/use-hash-location"; +import { useHashLocation } from "wouter/use-hash-location"; import { waitForHashChangeEvent } from "./test-utils"; import { ReactNode, useSyncExternalStore } from "react"; @@ -29,14 +29,6 @@ it("isn't sensitive to leading slash", () => { expect(path).toBe("/app/users"); }); -it("isn't sensitive to query string", () => { - location.hash = "/app/users?foo=bar"; - const { result } = renderHook(() => useHashLocation()); - const [path] = result.current; - - expect(path).toBe("/app/users"); -}); - it("rerenders when hash changes", async () => { const { result } = renderHook(() => useHashLocation()); @@ -204,16 +196,3 @@ it("defines a custom way of rendering link hrefs", () => { expect(getByTestId("link")).toHaveAttribute("href", "#/app"); }); - -it("useSearch returns correct query string when useHashLocation is used", () => { - location.hash = "/"; - const { result } = renderHook(() => useHashLocation()); - const [, navigate] = result.current; - - navigate("/?hello=world"); - const { - result: { current: search }, - } = renderHook(() => useSearch()); - - expect(search).toBe("hello=world"); -}); diff --git a/packages/wouter/types/use-browser-location.d.ts b/packages/wouter/types/use-browser-location.d.ts index d3b3ca3..6485d76 100644 --- a/packages/wouter/types/use-browser-location.d.ts +++ b/packages/wouter/types/use-browser-location.d.ts @@ -1,13 +1,6 @@ import { Path, SearchString } from "./location-hook.js"; -export type Primitive = - | string - | number - | bigint - | boolean - | null - | undefined - | symbol; +type Primitive = string | number | bigint | boolean | null | undefined | symbol; export const useLocationProperty: <S extends Primitive>( fn: () => S, ssrFn?: () => S diff --git a/packages/wouter/types/use-hash-location.d.ts b/packages/wouter/types/use-hash-location.d.ts index b9d9d1f..e3573c5 100644 --- a/packages/wouter/types/use-hash-location.d.ts +++ b/packages/wouter/types/use-hash-location.d.ts @@ -1,15 +1,7 @@ import { Path } from "./location-hook.js"; -import { BrowserSearchHook, Primitive } from "./use-browser-location.js"; export function navigate<S = any>(to: Path, options?: { state: S }): void; -export const useLocationProperty: <S extends Primitive>( - fn: () => S, - ssrFn?: () => S -) => S; - -export const useSearch: BrowserSearchHook; - export function useHashLocation(options?: { ssrPath?: Path; }): [Path, typeof navigate];