ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

react-use 的 useLocation:在 React 中响应式追踪浏览器 location 的完整指南

react-use 的 useLocation:在 React 中响应式追踪浏览器 location 的完整指南 react-use 的 useLocation在 React 中响应式追踪浏览器 location 的完整指南【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-useuseLocation是 react-use 提供的一个Sensor传感器类 Hook用于在 React 组件中响应式地跟踪浏览器当前的location信息。本文将以其官方文档 docs/useLocation.md 为核心结合 src/useLocation.ts 的源码实现讲解它的返回结构、底层事件机制、SSR 兼容策略以及在实际项目中的使用方式帮助你快速掌握URL 变化即组件重新渲染的响应式编程姿势。一、useLocation 是什么useLocation是一个 React sensor hook用于跟踪浏览器的位置信息。它的核心价值在于当浏览器的 URL 发生变化时无论是通过前进/后退按钮还是通过history.pushState/history.replaceState编程式跳转Hook 内部的状态会自动更新并触发使用它的组件重新渲染从而拿到最新的location快照。在 react-use 的 Hook 分类中它与useHash、useSearchParam、useMedia等同属于 Sensors 家族官方文档位于 docs/useLocation.md。需要注意的是官方文档描述其为 tracks browers location并且特别提示在 Internet Explorer 中需要先安装 polyfill对应 react-use 仓库 issue #73 中讨论的Event构造器缺失问题下文会展开说明。二、快速上手基础用法1. 引入与最小示例从 react-use 中引入useLocation调用它即可拿到一个描述当前页面位置的对象import {useLocation} from react-use; const Demo () { const state useLocation(); return ( pre {JSON.stringify(state, null, 2)} /pre ); };这是官方文档给出的原始示例useLocation()不需要任何参数返回的对象可以直接序列化为 JSON 展示。当 URL 变化时state会自动刷新pre中的内容也会随之更新。2. 返回对象的完整结构从源码 src/useLocation.ts 中的LocationSensorState接口可以看到返回值包含以下字段字段类型含义triggerstring本次状态更新的触发来源取值为load、popstate、pushstate、replacestatestateany当前history.state即pushState/replaceState时写入的自定义状态数据lengthnumber当前会话的 history 记录条数hashstringURL 中#之后的部分含#hoststring主机名和端口号如example.com:8080hostnamestring主机名如example.comhrefstring完整的 URLoriginstring协议 主机 端口如https://example.com:8080pathnamestring路径部分如/docs/useLocationportstring端口号如8080默认端口为空字符串protocolstring协议如https:searchstring查询字符串如?edit123含?其中hash、host、hostname、href、origin、pathname、port、protocol、search直接来自window.location而state与length来自window.history这一点在源码的buildState函数中有清晰的体现src/useLocation.ts。注意trigger是 react-use 为该 Hook 额外引入的字段用来标识状态更新的来源事件这在排查是什么操作触发了重新渲染时非常有用。三、底层原理源码级解析1. 双实现分支浏览器端与服务器端useLocation的源码末尾通过条件判断决定导出哪一个实现src/useLocation.tsconst hasEventConstructor typeof Event function; export default isBrowser hasEventConstructor ? useLocationBrowser : useLocationServer;也就是说浏览器环境且Event构造器可用→ 使用useLocationBrowser完整功能非浏览器环境SSR或缺少Event构造器的旧浏览器→ 回退到useLocationServer。useLocationServer的实现非常简单src/useLocation.ts只返回一个静态对象避免在服务端渲染时访问window导致报错const useLocationServer (): LocationSensorState ({ trigger: load, length: 1, });这正是 react-use 保证 SSR 安全isomorphic的一贯做法isBrowser的定义在 src/misc/util.ts 中typeof window ! undefined。2. 核心机制补丁 pushState / replaceState 监听三类事件浏览器端的useLocationBrowser做了两件事src/useLocation.ts第一初始化状态。通过useState(buildState(load))在组件挂载时读取一次当前的window.history与window.location快照trigger标记为load。第二在useEffect中注册三个事件监听器const onPopstate () setState(buildState(popstate)); const onPushstate () setState(buildState(pushstate)); const onReplacestate () setState(buildState(replacestate)); on(window, popstate, onPopstate); on(window, pushstate, onPushstate); on(window, replacestate, onReplacestate); return () { off(window, popstate, onPopstate); off(window, pushstate, onPushstate); off(window, replacestate, onReplacestate); };这里的关键点在于popstate是浏览器原生事件前进/后退时触发但pushstate和replacestate并不是原生事件——它们是 react-use 在模块加载时通过patchHistoryMethod手动补丁出来的src/useLocation.tsconst patchHistoryMethod (method) { const history window.history; const original history[method]; history[method] function (state) { const result original.apply(this, arguments); const event new Event(method.toLowerCase()); (event as any).state state; window.dispatchEvent(event); return result; }; }; if (isBrowser) { patchHistoryMethod(pushState); patchHistoryMethod(replaceState); }这段代码在模块顶层isBrowser为真时对window.history.pushState和window.history.replaceState做了包装调用原始方法完成跳转后再手动dispatchEvent一个同名的自定义事件pushstate/replacestate并把传入的state挂到事件的state属性上。这样一来无论用户是通过浏览器前进/后退还是通过pushState/replaceState编程式跳转useLocation都能感知到并刷新状态——这正是该 Hook 能全方位跟踪 URL 变化的秘密所在。事件监听的on/off工具函数来自 src/misc/util.ts内部对addEventListener/removeEventListener做了空值保护组件卸载时useEffect的清理函数会移除全部监听器避免内存泄漏。3. 为什么 IE 需要 polyfill补丁代码中使用了new Event(...)构造器而IE 不支持Event构造器它只支持document.createEvent。因此官方文档特别提示在 Internet Explorer 中使用useLocation需要先安装 polyfill。同时源码中的hasEventConstructor检查也保证了在缺少Event构造器的环境中Hook 会安全回退到useLocationServer不至于直接崩溃。四、在真实项目中驱动 URL 变化1. 通过 pushState 触发更新history.pushState是单页应用中最常见的无刷新跳转方式。结合上面的源码分析调用pushState会触发 react-use 补丁出的pushstate事件进而刷新 Hook 状态。仓库中的 Storybook 演示 stories/useLocation.story.tsx 给出了一个可直接运行的最小示例import { storiesOf } from storybook/react; import * as React from react; import { useLocation } from ../src; const go (page) window.history.pushState({}, , page); const Demo () { const state useLocation(); return ( div button onClick{() go(page-1)}Page 1/button button onClick{() go(page-2)}Page 2/button pre{JSON.stringify(state, null, 2)}/pre /div ); };点击 Page 1 / Page 2 两个按钮后URL 的pathname会变为.../page-1或.../page-2而state.trigger会变为pushstatepre中的 JSON 也会实时刷新。这个 Story 还展示了useLocation与ShowDocs组件的配合方式说明文档与可运行 Demo 是一一对应的。2. 在业务组件中的典型用法在实际应用中你通常需要根据 URL 的变化执行副作用例如根据路由参数重新拉取数据、更新面包屑或高亮导航菜单。可以配合useEffect使用import {useLocation, useEffectOnce} from react-use; const PageTracker () { const location useLocation(); useEffectOnce(() { // 首次挂载时的逻辑可选 }); // 每次 URL 变化都会触发重新渲染从而执行这里的副作用 // 例如上报埋点trackPageView(location.href); return ( div p当前路径{location.pathname}/p p查询参数{location.search}/p pHash{location.hash}/p /div ); };由于useLocation返回的是一个包含 12 个字段的新对象URL 变化时该对象必然是新引用因此直接把它放进useEffect的依赖数组即可可靠地触发副作用。3. 与 useHash、useSearchParam 的分工react-use 还提供了两个更聚焦的姊妹 HookuseHash只跟踪window.location.hashuseSearchParam只跟踪 URL 的某个查询参数如?edit123。它们内部同样依赖history.pushState驱动的更新机制参见 docs/useSearchParam.md 中的按钮示例。当你只需要 hash 或单个查询参数时优先使用它们可以获得更精简的返回值而useLocation适合需要完整 location 快照的场景。4. 已知限制与 Hash 路由的冲突使用useLocation以及useSearchParam时需要注意如果项目使用了 Hash 路由如react-router的HashRouter浏览器会把?search参数视为 URL hash 的一部分window.location.search将无法读到它们。这一点在 docs/useSearchParam.md 的 Caveats/Gotchas 一节有明确警示。因此若你的应用基于 Hash 路由useLocation返回的search字段可能为空需要改用从hash中解析参数。五、SSR 与兼容性要点SSR 安全非浏览器环境下自动回退到useLocationServer返回{ trigger: load, length: 1 }不会因为访问window而抛错可以放心用于 Next.js 等服务端渲染场景。IE 兼容IE 下需要为Event构造器安装 polyfill否则会走useLocationServer分支失去实时跟踪能力。自动清理组件卸载时useEffect的清理函数会移除popstate、pushstate、replacestate三个监听器无需手动管理。六、结语useLocation以极简的 API零参数调用封装了浏览器historylocation的完整状态跟踪能力通过补丁pushState/replaceState并监听popstate事件它把URL 变化这一浏览器级事件无缝转化为 React 状态更新同时借助双实现分支保证了 SSR 与旧浏览器的可用性。无论你是要实现路由联动组件、URL 驱动的数据请求还是想深入理解 react-use 的 sensor 类 Hook 设计思路docs/useLocation.md 与 src/useLocation.ts 都是值得反复研读的范本。【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表