CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
use-browser-location.js91 linesDownload Raw Back to src
1import { useSyncExternalStore } from "./react-deps.js";2 3/**4 * History API docs @see https://developer.mozilla.org/en-US/docs/Web/API/History5 */6const eventPopstate = "popstate";7const eventPushState = "pushState";8const eventReplaceState = "replaceState";9const eventHashchange = "hashchange";10const events = [11  eventPopstate,12  eventPushState,13  eventReplaceState,14  eventHashchange,15];16 17const subscribeToLocationUpdates = (callback) => {18  for (const event of events) {19    addEventListener(event, callback);20  }21  return () => {22    for (const event of events) {23      removeEventListener(event, callback);24    }25  };26};27 28export const useLocationProperty = (fn, ssrFn) =>29  useSyncExternalStore(subscribeToLocationUpdates, fn, ssrFn);30 31const currentSearch = () => location.search;32 33export const useSearch = ({ ssrSearch } = {}) =>34  useLocationProperty(35    currentSearch,36    // != null checks for both null and undefined, but allows empty string ""37    // This allows proper hydration: server renders with ssrSearch="?foo",38    // client hydrates with just <Router /> and reads from location.search39    ssrSearch != null ? () => ssrSearch : currentSearch40  );41 42const currentPathname = () => location.pathname;43 44export const usePathname = ({ ssrPath } = {}) =>45  useLocationProperty(46    currentPathname,47    // != null checks for both null and undefined, but allows empty string ""48    // This allows proper hydration: server renders with ssrPath="/foo",49    // client hydrates with just <Router /> and reads from location.pathname50    ssrPath != null ? () => ssrPath : currentPathname51  );52 53const currentHistoryState = () => history.state;54export const useHistoryState = () =>55  useLocationProperty(currentHistoryState, () => null);56 57export const navigate = (to, { replace = false, state = null } = {}) =>58  history[replace ? eventReplaceState : eventPushState](state, "", to);59 60// the 2nd argument of the `useBrowserLocation` return value is a function61// that allows to perform a navigation.62export const useBrowserLocation = (opts = {}) => [usePathname(opts), navigate];63 64const patchKey = Symbol.for("wouter_v3");65 66// While History API does have `popstate` event, the only67// proper way to listen to changes via `push/replaceState`68// is to monkey-patch these methods.69//70// See https://stackoverflow.com/a/458503171if (typeof history !== "undefined" && typeof window[patchKey] === "undefined") {72  for (const type of [eventPushState, eventReplaceState]) {73    const original = history[type];74    // TODO: we should be using unstable_batchedUpdates to avoid multiple re-renders,75    // however that will require an additional peer dependency on react-dom.76    // See: https://github.com/reactwg/react-18/discussions/86#discussioncomment-156714977    history[type] = function () {78      const result = original.apply(this, arguments);79      const event = new Event(type);80      event.arguments = arguments;81 82      dispatchEvent(event);83      return result;84    };85  }86 87  // patch history object only once88  // See: https://github.com/molefrog/wouter/issues/16789  Object.defineProperty(window, patchKey, { value: true });90}91