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];