
如果简短
在本文中,我们将创建一个usePosition()
反应性挂钩来跟踪浏览器的地理位置。 在watchPosition()
,此钩子将使用本机浏览器对象navigator.geolocation的getCurrentPosition()
和watchPosition()
方法。 我在GitHub和NPM 上发布了该钩子的最终版本。
为什么原则上创建usePosition()
钩子
React中钩子的重要优点之一是能够在一个位置(在钩子中)隔离逻辑相关的代码片段,同时避免了例如在componentDidMount()
方法中混合逻辑上不相关的代码片段的需要。
假设我们要获取浏览器坐标( latitude
和longitude
),并在接收到坐标后,从第三方服务请求天气预报或该区域的当前温度。 React中的这两个功能(获取坐标和请求温度)的代码通常放在一个componentDidMount()
方法中。 在这种情况下,通常会自行“清除” componentWillUnmount()方法,调用clearWatch()方法停止监视浏览器位置。 这种方法增加了方法的规模,将代码的逻辑连接部分分成多个部分(分别订阅和取消订阅,以监视浏览器的位置),并将代码的逻辑弱连接部分组合为一种方法(获取坐标和温度)。 读取代码非常困难,调试和支持也很困难。
接下来,我们将尝试将与获取浏览器坐标相关的功能转移到单独的usePosition()
挂钩中,以避免上面列出的困难。
我们将如何使用usePosition()
挂钩
让我们“相反”,在实现钩子本身之前,让我们计划一下如何使用它。 这将帮助我们确定钩子接口(它将接受什么以及返回什么)。
获取坐标并将其显示在屏幕上的最简单示例如下所示:
import React from 'react';
使用usePosition()
钩子仅需一行,我们就可以使用longitude
坐标进行操作。 这里甚至没有显式使用过useState()
或useEffect()
挂钩。 跟踪坐标的订阅以及删除订阅者都封装在一个usePosition()
挂钩中。 此外,重绘React组件的魔力将为我们做一切。 开始时,坐标将为null
或undefined
。 一旦收到坐标,组件将被重绘,我们将在屏幕上看到它们。
usePosition()
实现usePosition()
我们的usePosition()
挂钩是一个常规的JavaScript函数,如下所示:
我们将使用useState()挂钩来内部存储坐标,并使用useEffect()来订阅和取消订阅跟踪坐标。 为此,我们必须导入它们。
import { useState, useEffect } from 'react'; export const usePosition = () => {
我们将创建状态变量,其中将存储坐标或获取坐标时出错(例如,如果用户拒绝共享其位置)。
import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null);
同样在此阶段,我们可以返回挂钩中期望的变量。 到目前为止,这些变量没有什么用,但是我们会尽快修复。
import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null);
现在,实现的关键时刻就是获得坐标。
import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null);
在useEffect()
挂钩中,我们首先检查浏览器是否支持坐标检测功能。 如果不支持该功能,我们将退出并显示错误。 否则,我们订阅使用onChange onChange()
和onError()
更改浏览器的地理位置(我们将在下面添加其代码)。 请注意,从useEffect()
挂钩中,我们返回一个匿名函数,如果该组件从显示中删除,该函数将被执行。 在此匿名功能中,我们取消订阅监视,以免阻塞内存。 因此,订阅和取消订阅跟踪的整个逻辑都在一个usePosition()
挂钩中。
让我们添加缺少的回调:
import { useState, useEffect } from 'react'; export const usePosition = () => { const [position, setPosition] = useState({}); const [error, setError] = useState(null); const onChange = ({latitude, longitude}) => {
usePosition()
挂钩可以使用了。
最后
您可以找到该钩子及其更详细实现的演示,并能够在GitHub上设置跟踪参数。
希望本文对您有所帮助。 编码成功!