React 自定义挂钩允许在功能组件中使用可重用的逻辑,从而可以分离组件并保持部件较小并专注于它们的预期目的。自定义挂钩还可以更轻松地测试和理解组件的逻辑,因为它可以与组件本身隔离和单独测试。自定义钩子还可以让不同组件之间的共享逻辑变得更容易,减少代码重复,更容易维护和更新代码库。
React hooks 有无限的可能性,但并不是所有的都生而平等。在本文中,我将介绍 30 个强大的自定义挂钩,您可以在任何项目中使用它们,而且实施起来也超级快。
注意:Youtuber Web Dev Simplified创建了这些挂钩。如果你想要深入的视频解释,你可以查看他的视频。但是,如果您只是阅读它们,请继续。
目录
使用切换
使用超时
使用去抖动
使用更新效果
使用数组
使用上一个
使用StateWithHistory
使用存储
使用异步
使用Fetch
使用脚本
使用DeepCompareEffect
使用事件监听器
使用OnScreen
使用窗口大小
1.使用切换
import { useState } from “react”
export default function useToggle(defaultValue) {
const [value, setValue] = useState(defaultValue)
function toggleValue(value) {
setValue(currentValue =>
typeof value === “boolean” ? value : !currentValue
)
}
return [value, toggleValue]
}
useToggle是一个自定义的 React 钩子,它允许组件在 true 和 false 之间切换值。它使用useState钩子来管理它的状态。首先,钩子接受一个defaultValue参数来初始化值状态。然后,它返回一个包含两个元素的数组:当前值和一个用于toggleValue在 true 和 false 之间切换值的函数。该函数接受一个参数。如果参数是布尔值,它将值设置为参数。否则,它会切换当前值。
以下是如何使用此挂钩的示例:
import useToggle from “./useToggle”
export default function ToggleComponent() {
const [value, toggleValue] = useToggle(false)
return (
Toggle
<button onClick={() => toggleValue(true)}>Make True
<button onClick={() => toggleValue(false)}>Make False
)
}
2.使用超时
import { useCallback, useEffect, useRef } from “react”
export default function useTimeout(callback, delay) {
const callbackRef = useRef(callback)
const timeoutRef = useRef()
useEffect(() => {
callbackRef.current = callback
}, [callback])
const set = useCallback(() => {
timeoutRef.current = setTimeout(() => callbackRef.current(), delay)
}, [delay])
const clear = useCallback(() => {
timeoutRef.current && clearTimeout(timeoutRef.current)
}, [])
useEffect(() => {
set()
return clear
}, [delay, set, clear])
const reset = useCallback(() => {
clear()
set()
}, [clear, set])
return { reset, clear }
}
useTimeout是一个自定义的 React 挂钩,它允许组件set超时clear。它使用ReactuseCallback库中的、useEffect和useRef钩子。该钩子有两个参数:一个回调,将在指定的延迟后调用,延迟是调用回调之前应该经过的时间(以毫秒为单位)。
该挂钩返回一个具有两个属性的对象:reset和clear,可用于重置或清除超时的函数。
钩子使用useRef钩子创建两个引用:callbackRef和timeoutRef。将回调函数作为可变值保存,并callbackRef包含setTimeout()函数返回的超时ID。timeoutRef
useEffect 钩子用于确保callbackRef.current始终传递最新的回调。
该函数使用setTimeoutset创建一个新的超时,在指定的延迟后调用回调函数。clear函数使用clearTimeout清除超时。然后还有另一个钩子用于设置挂载超时并在卸载时将其删除。复位函数是和函数的组合。最后,钩子确保函数仅在它们的依赖关系发生变化时才重新创建。useEffectclearsetuseCallback
以下是如何使用此挂钩的示例:
import { useState } from “react”
import useTimeout from “./useTimeout”
export default function TimeoutComponent() {
const [count, setCount] = useState(10)
const { clear, reset } = useTimeout(() => setCount(0), 1000)
return (
<button onClick={() => setCount(c => c + 1)}>Increment
Clear Timeout
Reset Timeout
)
}
这个自定义useTimeout钩子在组件需要充当不可避免的延迟的各种情况下很有用。例如:
一定时间后消失的通知消息
在重定向之前显示加载微调器一定时间的表单提交
在一定时间后自动前进到下一张幻灯片的幻灯片
显示剩余时间并在达到零时触发动作的倒数计时器
一定时间后保存表单数据的自动保存功能
在一定数量的不活动后将用户注销的会话超时
延迟回调执行一定时间的去抖动函数。
它可以用在任何情况下,你需要在行动之前等待一定的时间,或者多次重复一个动作,并且在它们之间有延迟。
3.使用去抖动
import { useEffect } from “react”
import useTimeout from “…/2-useTimeout/useTimeout”
export default function useDebounce(callback, delay, dependencies) {
const { reset, clear } = useTimeout(callback, delay)
useEffect(reset, […dependencies, reset])
useEffect(clear, [])
}
useDebounce是一个自定义的 React 挂钩,它允许组件将回调函数的执行延迟指定的时间量。useEffect它使用来自 React 库的内置钩子和useTimeout(第二个自定义钩子)自定义钩子。
该钩子接受三个参数:
“回调”是应该去抖动的功能。
“延迟”是在调用回调之前应该经过的时间(以毫秒为单位)。
“dependencies”是一个值数组,钩子应该监听这些值的变化,并在有任何变化时重新运行回调。
钩子使用useTimeout钩子创建一个超时,该超时将在指定的延迟后调用回调函数。该useEffect钩子用于设置挂载超时并在卸载时清除超时。第一个useEffect将在任何依赖项更改时调用reset函数,第二个useEffect在组件卸载时调用 clear 函数。
下面是一个如何使用这个钩子的例子:
import { useState } from “react”
import useDebounce from “./useDebounce”
export default function DebounceComponent() {
const [count, setCount] = useState(10)
useDebounce(() => alert(count), 1000, [count])
return (
<button onClick={() => setCount(c => c + 1)}>Increment
)
}
如果您想限制在短时间内调用回调函数的次数,此挂钩会很有用。例如,当您有一个在每次击键时都会向服务器发送搜索请求的输入字段时,您应该等待用户停止输入后再发送请求,以避免不必要的网络流量并改善用户体验。
4.使用更新效果
import { useEffect, useRef } from “react”
export default function useUpdateEffect(callback, dependencies) {
const firstRenderRef = useRef(true)
useEffect(() => {
if (firstRenderRef.current) {
firstRenderRef.current = false
return
}
return callback()
}, dependencies)
}
useUpdateEffect是一个自定义的 React 钩子,它允许组件仅在特定依赖项发生变化时运行回调函数。它使用 React 库的内置useEffect和useRef钩子。
钩子接受两个参数:
callback是依赖项更改时应调用的函数
dependencies是一个值数组,钩子应该监听这些值的变化。
钩子使用useRef钩子创建一个firstRenderRef初始值为true的引用。该引用将用于跟踪组件的第一次渲染。
useEffect hook 用于监听 dependencies 数组的变化并调用回调函数。在useEffect函数内部,它通过检查值来检查这是否是组件的第一次渲染firstRenderRef。如果是,则将其设置为 false 并返回。如果不是,说明这是一次更新,所以会调用回调函数,返回回调函数。
下面是一个如何使用这个钩子的例子:
import { useState } from “react”
import useUpdateEffect from “./useUpdateEffect”
export default function UpdateEffectComponent() {
const [count, setCount] = useState(10)
useUpdateEffect(() => alert(count), [count])
return (
<button onClick={() => setCount(c => c + 1)}>Increment
)
}
如果您只想在特定值更改时而不是在初始渲染时运行某些逻辑,此挂钩会很有帮助。例如,当您希望在用户从下拉菜单中选择特定选项后从 API 获取数据时,或者当您希望在窗口大小更改后更新元素在屏幕上的位置时。
5.使用数组
import { useState } from “react”
export default function useArray(defaultValue) {
const [array, setArray] = useState(defaultValue)
function push(element) {
setArray(a => […a, element])
}
function filter(callback) {
setArray(a => a.filter(callback))
}
function update(index, newElement) {
setArray(a => [
…a.slice(0, index),
newElement,
…a.slice(index + 1, a.length),
])
}
function remove(index) {
setArray(a => […a.slice(0, index), …a.slice(index + 1, a.length)])
}
function clear() {
setArray([])
}
return { array, set: setArray, push, filter, update, remove, clear }
}
useArray是一个自定义的 React 钩子,它允许组件管理数组状态。useState它使用React 库中的内置钩子。该挂钩接受一个参数 ,defaultValue用于初始化数组状态。该钩子返回一个具有多个属性的对象:
array是当前数组状态
set是一个允许您将数组状态设置为新值的函数
push是一个函数,使您能够将一个元素添加到数组的末尾
filter是一个允许您通过传递回调函数来过滤数组的函数
update是一个使您能够更新数组特定索引处的元素的函数
remove是一个函数,它允许您将元素删除到数组的特定索引
clear是一个使您能够清除数组的函数。
所有更改数组状态的函数都使用 setArray 函数。尽管如此,他们还是通过创建新数组、添加或删除元素,然后将其传递给 setArray 函数来保持状态的不变性。
下面是一个如何使用这个钩子的例子:
import useArray from “./useArray”
export default function ArrayComponent() {
const { array, set, push, remove, filter, update, clear } = useArray([
1, 2, 3, 4, 5, 6,
])
return (
<button onClick={() => push(7)}>Add 7
<button onClick={() => update(1, 9)}>Change Second Element To 9
<button onClick={() => remove(1)}>Remove Second Element
<button onClick={() => filter(n => n < 3)}>
Keep Numbers Less Than 4
<button onClick={() => set([1, 2])}>Set To 1, 2
Clear
)
}
如果您想管理组件状态下的数据数组并执行日常数组操作(例如添加、删除、更新和过滤元素),此挂钩会很有帮助。
6.使用上一个
import { useRef } from “react”
export default function usePrevious(value) {
const currentRef = useRef(value)
const previousRef = useRef()
if (currentRef.current !== value) {
previousRef.current = currentRef.current
currentRef.current = value
}
return previousRef.current
}
usePrevious是一个自定义的 React 钩子,它允许组件跟踪变量的先前值。它使用ReactuseRef库中的内置钩子。
钩子接受一个参数value,它是变量的当前值。然后,它创建两个引用,一个称为currentRef,其中保存变量的当前值,另一个称为previousRef,其中包含变量的先前值。
挂钩将当前值与先前值进行比较。如果不同,它将使用当前值更新 previousRef 并使用新值更新 currentRef。然后它返回previousRef.current.
下面是一个如何使用这个钩子的例子:
import { useState } from “react”
import usePrevious from “./usePrevious”
export default function PreviousComponent() {
const [count, setCount] = useState(0)
const [name, setName] = useState(“Kyle”)
const previousCount = usePrevious(count)
return (
{count} - {previousCount}
<button onClick={() => setCount(currentCount => currentCount + 1)}>
Increment
<button onClick={() => setName(“John”)}>Change Name
)
}
此挂钩在需要访问变量的先前值的情况下很有用,例如,当您想要将当前值与之前的值进行比较以检查它是否已更改或当您想要跟踪更改时随时间变化的变量。
7.使用StateWithHistory
import { useCallback, useRef, useState } from “react”
export default function useStateWithHistory(
defaultValue,
{ capacity = 10 } = {}
) {
const [value, setValue] = useState(defaultValue)
const historyRef = useRef([value])
const pointerRef = useRef(0)
const set = useCallback(
v => {
const resolvedValue = typeof v === “function” ? v(value) : v
if (historyRef.current[pointerRef.current] !== resolvedValue) {
if (pointerRef.current < historyRef.current.length - 1) {
historyRef.current.splice(pointerRef.current + 1)
}
historyRef.current.push(resolvedValue)
while (historyRef.current.length > capacity) {
historyRef.current.shift()
}
pointerRef.current = historyRef.current.length - 1
}
setValue(resolvedValue)
},
[capacity, value]
)
const back = useCallback(() => {
if (pointerRef.current <= 0) return
pointerRef.current–
setValue(historyRef.current[pointerRef.current])
}, [])
const forward = useCallback(() => {
if (pointerRef.current >= historyRef.current.length - 1) return
pointerRef.current++
setValue(historyRef.current[pointerRef.current])
}, [])
const go = useCallback(index => {
if (index < 0 || index > historyRef.current.length - 1) return
pointerRef.current = index
setValue(historyRef.current[pointerRef.current])
}, [])
return [
value,
set,
{
history: historyRef.current,
pointer: pointerRef.current,
back,
forward,
go,
},
]
}
useStateWithHistory是一个自定义的 React 挂钩,它允许组件跟踪状态的历史记录。它使用来自 React 库的内置useState、useCallback和钩子。useRef
钩子接受两个参数:
defaultValue是状态的初始值
capacity是一个可选参数,用于设置应存储在历史记录中的最大状态数。
该钩子创建了两个引用,一个被称为historyRef保存状态历史数组,另一个被称为pointerRef具有历史的当前指针。它还创建了三个回调函数:set、back和forward。
该set函数用于设置状态,它的工作方式与内置函数类似setState,但它还通过将新值添加到历史数组并更新 pointerRef 来跟踪状态的历史记录。该函数可以接受一个值或一个接收当前状态作为参数的回调函数。该函数还通过删除最旧的元素来确保不超过历史数组的容量。
该back函数导航历史记录中的先前状态。它递减pointerRef并使用历史数组的较早值更新状态。
该forward函数导航历史记录中的下一个状态。它递增 pointerRef 并使用历史数组中的下一个值更新状态。
该go函数导航历史记录中的特定状态。它将 pointerRef 设置为作为参数传递的索引,并使用历史数组中该索引处的值更新状态。
该钩子返回一个包含两个元素的数组:
当前状态值
一个包含历史数组、指针和函数set、back、forward和的对象go。
下面是一个如何使用这个钩子的例子:
import { useState } from “react”
import useStateWithHistory from “./useStateWithHistory”
export default function StateWithHistoryComponent() {
const [count, setCount, { history, pointer, back, forward, go }] =
useStateWithHistory(1)
const [name, setName] = useState(“Kyle”)
return (
<button onClick={() => setCount(currentCount => currentCount * 2)}>
Double
<button onClick={() => setCount(currentCount => currentCount + 1)}>
Increment
Back
Forward
<button onClick={() => go(2)}>Go To Index 2
<button onClick={() => setName(“John”)}>Change Name
)
}
此挂钩在您想要跟踪状态历史记录的情况下很有用,例如,当您想要实现撤消或重做功能或允许用户浏览更改历史记录时。
8.使用存储
import { useCallback, useState, useEffect } from “react”
export function useLocalStorage(key, defaultValue) {
return useStorage(key, defaultValue, window.localStorage)
}
export function useSessionStorage(key, defaultValue) {
return useStorage(key, defaultValue, window.sessionStorage)
}
function useStorage(key, defaultValue, storageObject) {
const [value, setValue] = useState(() => {
const jsonValue = storageObject.getItem(key)
if (jsonValue != null) return JSON.parse(jsonValue)
if (typeof defaultValue === "function") {
return defaultValue()
} else {
return defaultValue
}
})
useEffect(() => {
if (value === undefined) return storageObject.removeItem(key)
storageObject.setItem(key, JSON.stringify(value))
}, [key, value, storageObject])
const remove = useCallback(() => {
setValue(undefined)
}, [])
return [value, setValue, remove]
}
useLocalStorage并且useSessionStorage是一个自定义的 React 挂钩,它允许组件将值存储在浏览器的LocalStorage或SessionStorage中,并使其与组件的状态保持同步。它使用React 库中的内置useState和钩子以及钩子。useEffectuseCallback
和功能类似,但分别使用不同的useLocalStorage存储localStorage和sessionStorage。他们接受两个参数:和。是用于在存储对象中存储值的键,是在存储对象中找不到该键时将使用的值。useSessionStoragekeydefaultValuekeydefaultValue
这两个函数都使用storage函数,它接受三个参数:key, defaultValue, 和storageObject并返回一个包含三个元素的数组:
当前值
可用于更新状态和存储中的值的函数“setValue”。
可用于从状态和存储中删除值的“删除”函数。
useEffect挂钩使存储在浏览器存储器中的值与组件的状态保持同步。
该useStorage函数使用JSON.stringify()和JSON.parse方法在将值存储在存储对象中时将值转换为JSON字符串,并在从存储对象中检索值时将其转换回 JavaScript 对象。这允许挂钩处理任何数据,而不仅仅是字符串。
useEffect只要key、value或storageObject发生变化,挂钩就会运行。首先,它检查该值是否未定义。在这种情况下,它会从存储对象中删除该项目。否则,它将值存储在存储对象中。
下面是一个如何使用这个钩子的例子:
import { useSessionStorage, useLocalStorage } from “./useStorage”
export default function StorageComponent() {
const [name, setName, removeName] = useSessionStorage(“name”, “Kyle”)
const [age, setAge, removeAge] = useLocalStorage(“age”, 26)
return (
{name} - {age}
<button onClick={() => setName(“John”)}>Set Name
<button onClick={() => setAge(40)}>Set Age
Remove Name
Remove Age
)
}
在您希望跨浏览器会话或页面持久保存数据并使数据与组件状态保持同步的情况下,此挂钩很有用。例如,您可以存储用户设置、表单数据或待办事项列表。使用 useLocalStorage 和 useSessionStorage 挂钩可以根据需要灵活地使用浏览器的本地存储或会话存储。
9.使用异步
import { useCallback, useEffect, useState } from “react”
export default function useAsync(callback, dependencies = []) {
const [loading, setLoading] = useState(true)
const [error, setError] = useState()
const [value, setValue] = useState()
const callbackMemoized = useCallback(() => {
setLoading(true)
setError(undefined)
setValue(undefined)
callback()
.then(setValue)
.catch(setError)
.finally(() => setLoading(false))
}, dependencies)
useEffect(() => {
callbackMemoized()
}, [callbackMemoized])
return { loading, error, value }
}
useAsync是一个自定义的 React 挂钩,它允许组件处理异步操作并跟踪loading、error和value状态。它使用React 库中的内置useState和钩子以及钩子。useEffectuseCallback
钩子接受两个参数:
callback是一个返回承诺的函数。该函数负责执行异步操作。
dependencies是钩子应该侦听更改的依赖项数组。回调函数将在任何依赖项更改时执行。
该钩子创建了三个状态变量:loading、error和value。加载状态用于指示异步操作当前是否正在进行,错误状态用于在承诺被拒绝的情况下存储错误对象,而值状态用于在承诺实现的情况下存储已解析的值.
callbackMemoized该挂钩还创建了一个名为using的回调函数useCallback。该函数将loading、error和value状态设置为它们的初始值,然后调用传入的回调函数。当依赖项发生变化时,
钩子useEffect调用 callbackMemoized 函数。
下面是一个如何使用这个钩子的例子:
import useAsync from “./useAsync”
export default function AsyncComponent() {
const { loading, error, value } = useAsync(() => {
return new Promise((resolve, reject) => {
const success = false
setTimeout(() => {
success ? resolve(“Hi”) : reject(“Error”)
}, 1000)
})
})
return (
)
}
此挂钩在您想要处理异步操作(例如从 API 获取数据、上传文件或将数据保存到数据库)的情况下非常有用。它提供了一种简单的方法来管理组件中的加载、错误和值状态,还允许组件在某些值更改时重新运行异步操作。
10.使用获取
import useAsync from “…/9-useAsync/useAsync”
const DEFAULT_OPTIONS = {
headers: { “Content-Type”: “application/json” },
}
export default function useFetch(url, options = {}, dependencies = []) {
return useAsync(() => {
return fetch(url, { …DEFAULT_OPTIONS, …options }).then(res => {
if (res.ok) return res.json()
return res.json().then(json => Promise.reject(json))
})
}, dependencies)
}
useFetch是一个自定义的 React 挂钩,它允许组件处理从 URL 获取数据并跟踪加载、错误和值状态。它使用内置的获取API 和自定义挂钩useAsync,允许组件处理异步操作并跟踪加载、错误和值状态。
该钩子接受三个参数:
URL是要从中获取数据的端点的 URL
options是一个包含选项的对象,例如获取请求的标头、方法和正文。
dependencies是钩子应该侦听更改的依赖项数组。回调函数将在任何依赖项更改时执行。
该挂钩创建一个回调函数,该函数使用 fetch API 来请求具有传入选项和默认选项的给定URL 。
然后检查响应是否正常。如果是,它以 json 格式返回响应。如果不是,它返回 JSON 响应并拒绝它。
下面是一个如何使用这个钩子的例子:
import { useState } from “react”
import useFetch from “./useFetch”
export default function FetchComponent() {
const [id, setId] = useState(1)
const { loading, error, value } = useFetch(
https://jsonplaceholder.typicode.com/todos/${id},
{},
[id]
)
return (
<button onClick={() => setId(currentId => currentId + 1)}>
Increment ID
)
}
在您想要处理从 API 获取数据的情况下,此挂钩会很有帮助。它提供了一种简单的方法来管理组件中的加载、错误和值状态,并且还允许组件。
11.使用脚本
import useAsync from “…/9-useAsync/useAsync”
export default function useScript(url) {
return useAsync(() => {
const script = document.createElement(“script”)
script.src = url
script.async = true
return new Promise((resolve, reject) => {
script.addEventListener("load", resolve)
script.addEventListener("error", reject)
document.body.appendChild(script)
})
}, [url])
}
useScript是一个自定义的 React 挂钩,它允许组件从给定的 URL 加载 JavaScript 文件并跟踪加载、错误和值状态。此外,它还使用useAsync允许组件处理异步操作并跟踪加载、错误和值状态的自定义挂钩。
钩子接受一个参数:
URL是要加载的 JavaScript 文件的 URL。
该挂钩创建一个回调函数,该函数使用 DOM API 创建一个新的脚本元素并将其 src 设置为传入的 URL。它还将该属性设置async为 true。
然后它返回一个新的承诺,当脚本加载或出错时分别解决或拒绝。
下面是一个如何使用这个钩子的例子:
import useScript from “./useScript”
export default function ScriptComponent() {
const { loading, error } = useScript(
“https://code.jquery.com/jquery-3.6.0.min.js”
)
if (loading) return
if (error) return
return
}
这个钩子在你想要动态加载外部 JavaScript 库的情况下很有用。它提供了一种管理组件的加载、错误和值状态的简单方法,还允许组件在 URL 更改时重新加载脚本。
12.使用DeepCompareEffect
import { useEffect, useRef } from “react”
import isEqual from “lodash/fp/isEqual”
export default function useDeepCompareEffect(callback, dependencies) {
const currentDependenciesRef = useRef()
if (!isEqual(currentDependenciesRef.current, dependencies)) {
currentDependenciesRef.current = dependencies
}
useEffect(callback, [currentDependenciesRef.current])
}
useDeepCompareEffect是一个自定义的 React 钩子,它允许组件仅在依赖关系发生变化时使用深度比较而不是浅层比较来运行效果。useEffect它使用React 库中的内置钩子和 lodash isEqual 函数进行深度比较。
钩子有两个参数:
callback是一个函数,表示被执行的效果。
dependencies是效果所依赖的值数组。
它还会创建一个 ref 调用currentDependenciesRef来存储当前的依赖项。
然后它使用该函数将当前依赖项与新依赖项进行比较isEqual。如果它们不相等,它会用新的依赖项更新当前的依赖项 ref。
然后它调用带有回调函数的 useEffect 和 currentDependenciesRef.current 作为依赖项。
下面是一个如何使用这个钩子的例子:
import { useEffect, useState, useRef } from “react”
import useDeepCompareEffect from “./useDeepCompareEffect”
export default function DeepCompareEffectComponent() {
const [age, setAge] = useState(0)
const [otherCount, setOtherCount] = useState(0)
const useEffectCountRef = useRef()
const useDeepCompareEffectCountRef = useRef()
const person = { age: age, name: “Kyle” }
useEffect(() => {
useEffectCountRef.current.textContent =
parseInt(useEffectCountRef.current.textContent) + 1
}, [person])
useDeepCompareEffect(() => {
useDeepCompareEffectCountRef.current.textContent =
parseInt(useDeepCompareEffectCountRef.current.textContent) + 1
}, [person])
return (
useEffect: 0
useDeepCompareEffect: 0
<button onClick={() => setAge(currentAge => currentAge + 1)}>
Increment Age
<button onClick={() => setOtherCount(count => count + 1)}>
Increment Other Count
)
}
此挂钩在依赖项是复杂对象或数组的情况下很有用,并且您希望确保效果仅在依赖项中的特定值发生更改时运行。它可以帮助防止不必要的重新渲染并提高性能。
- 使用事件监听器
import { useEffect, useRef } from “react”
export default function useEventListener(
eventType,
callback,
element = window
) {
const callbackRef = useRef(callback)
useEffect(() => {
callbackRef.current = callback
}, [callback])
useEffect(() => {
if (element == null) return
const handler = e => callbackRef.current(e)
element.addEventListener(eventType, handler)
return () => element.removeEventListener(eventType, handler)
}, [eventType, element])
}
useEventListener是一个自定义的 React 钩子,它允许组件向特定的 DOM 元素添加事件监听器,并在事件发生时执行回调函数。useEffect它使用React 库中的内置钩子。
钩子接受三个参数:
eventType是一个字符串,表示要侦听的事件类型,例如“click”或“keydown”。
回调是一个函数,表示事件发生时要采取的操作。
element是一个可选的DOM元素,用于添加事件监听器。默认值为window,这意味着事件监听器将被添加到全局 window 对象。
它还创建一个 ref calledcallbackRef来存储当前的回调函数。
useEffect hook 用于在组件挂载时设置事件侦听器,并在组件卸载时移除事件侦听器。当回调函数发生变化时,它还会更新回调 ref。
下面是一个如何使用这个钩子的例子:
import { useState } from “react”
import useEventListener from “./useEventListener”
export default function EventListenerComponent() {
const [key, setKey] = useState(“”)
useEventListener(“keydown”, e => {
setKey(e.key)
})
return
}
如果您希望以声明方式处理单击、按键或表单提交等事件,并使组件逻辑与事件处理逻辑分离,则此挂钩很有用。
14.使用屏幕
import { useEffect, useState } from “react”
export default function useOnScreen(ref, rootMargin = “0px”) {
const [isVisible, setIsVisible] = useState(false)
useEffect(() => {
if (ref.current == null) return
const observer = new IntersectionObserver(
([entry]) => setIsVisible(entry.isIntersecting),
{ rootMargin }
)
observer.observe(ref.current)
return () => {
if (ref.current == null) return
observer.unobserve(ref.current)
}
}, [ref.current, rootMargin])
return isVisible
}
useOnScreen是一个自定义的 React 钩子,它允许组件检测特定DOM元素何时在视口中可见并跟踪可见性状态。useEffect它使用来自 React 库的内置钩子和IntersectionObserver API。
钩子有两个参数:
ref是对 DOM 元素的引用以检测可见性,通常使用 React“useRef”挂钩创建。
rootMargin是一个可选字符串,用于定义根元素周围的偏移量。它可用于在检查交叉点之前放大或缩小根元素的边界框。默认值为“0px”。
useEffect hook 用于在组件挂载时设置IntersectionObserver并在组件卸载时移除观察者。它还会在 ref 或 rootMargin 更改时更新观察者。 它返回一个布尔值,指示 DOM 元素当前是否可见。
isVisible
下面是一个如何使用这个钩子的例子:
import { useRef } from “react”
import useOnScreen from “./useOnScreen”
export default function OnScreenComponentComponent() {
const headerTwoRef = useRef()
const visible = useOnScreen(headerTwoRef, “-100px”)
return (
Header
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Unde incidunt,
nam id itaque error dicta? Numquam earum iusto optio officia, molestias
debitis illum facilis nemo asperiores eaque voluptates modi? Dicta
mollitia fugit doloremque vitae, dolores sequi fuga quas vel incidunt
animi architecto dignissimos amet in quam praesentium corrupti voluptate
dolorem impedit numquam aut cupiditate nulla! Nisi dolore dicta, cumque
illum tempora enim dolores eum quis itaque nostrum architecto vel cum
officiis aperiam qui exercitationem voluptatibus. Veritatis unde
doloribus dolorem architecto, eum reprehenderit possimus similique eius
cum obcaecati totam placeat. Delectus nulla, quae temporibus omnis
assumenda autem ad quibusdam facilis aspernatur inventore nobis. Vitae
architecto, unde consequuntur velit consequatur dicta mollitia, fuga
iure hic accusamus blanditiis. Dignissimos, tenetur amet adipisci
nostrum perferendis ad rerum accusamus distinctio repellendus eius,
quisquam repellat nesciunt, consequatur culpa neque? Inventore vitae
laborum aperiam ullam dolorem officiis ipsum aliquid doloribus pariatur,
commodi iure illum soluta delectus, architecto ratione maiores
accusamus. Provident quia sequi dolorum asperiores necessitatibus
consequatur perspiciatis at a, inventore, deserunt corporis recusandae
earum vero voluptas saepe pariatur, libero illo. Numquam facilis magnam
exercitationem ipsam libero quidem minima dolores perferendis eveniet
impedit eos, nesciunt unde velit facere itaque eum quasi laboriosam
veritatis aliquid tenetur. Blanditiis exercitationem laborum, optio
nulla minima libero sed doloremque soluta, dignissimos tempora rerum id
nostrum iusto eveniet illo corrupti dicta. Non fuga exercitationem sit
dignissimos voluptatibus cumque nobis iste asperiores illum fugit
Header 2 {visible && “(Visible)”}
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Unde incidunt,
nam id itaque error dicta? Numquam earum iusto optio officia, molestias
debitis illum facilis nemo asperiores eaque voluptates modi? Dicta
mollitia fugit doloremque vitae, dolores sequi fuga quas vel incidunt
animi architecto dignissimos amet in quam praesentium corrupti voluptate
dolorem impedit numquam aut cupiditate nulla! Nisi dolore dicta, cumque
illum tempora enim dolores eum quis itaque nostrum architecto vel cum
officiis aperiam qui exercitationem voluptatibus. Veritatis unde
doloribus dolorem architecto, eum reprehenderit possimus similique eius
cum obcaecati totam placeat. Delectus nulla, quae temporibus omnis
assumenda autem ad quibusdam facilis aspernatur inventore nobis. Vitae
architecto, unde consequuntur velit consequatur dicta mollitia, fuga
iure hic accusamus blanditiis. Dignissimos, tenetur amet adipisci
nostrum perferendis ad rerum accusamus distinctio repellendus eius,
quisquam repellat nesciunt, consequatur culpa neque? Inventore vitae
laborum aperiam ullam dolorem officiis ipsum aliquid doloribus pariatur,
commodi iure illum soluta delectus, architecto ratione maiores
accusamus. Provident quia sequi dolorum asperiores necessitatibus
consequatur perspiciatis at a, inventore, deserunt corporis recusandae
earum vero voluptas saepe pariatur, libero illo. Numquam facilis magnam
exercitationem ipsam libero quidem minima dolores perferendis eveniet
impedit eos, nesciunt unde velit facere itaque eum quasi laboriosam
veritatis aliquid tenetur. Blanditiis exercitationem laborum, optio
nulla minima libero sed doloremque soluta, dignissimos tempora rerum id
nostrum iusto eveniet illo corrupti dicta. Non fuga exercitationem sit
dignissimos voluptatibus cumque nobis iste asperiores illum fugit
veritatis fugiat quia voluptates cupiditate vel rerum eligendi facere
sint nostrum quam, maiores dolorem repellat voluptas! Magnam ullam quis
quas aut consequuntur quo doloremque, earum sint soluta vero iste quasi
voluptates labore rerum aspernatur illum esse maxime laudantium? Tempore
perspiciatis perferendis ea dolorem et quasi eos illo beatae consectetur
maxime, enim ducimus corrupti, accusantium quisquam rem dolorum itaque
iste velit. Amet similique accusamus doloribus expedita modi a
architecto accusantium labore unde non, dolore totam quaerat sit
laboriosam quae ullam impedit, pariatur repudiandae quisquam debitis
repellendus nihil. Cumque blanditiis ut recusandae illum! Maiores
eveniet nulla exercitationem natus delectus est minus a architecto
pariatur molestias quo nihil maxime quasi facere magnam neque dolorem
ad, doloribus hic! Qui corporis perspiciatis dolores rem minima tenetur.
Fugit ipsa consectetur ad reiciendis, quia iste, sapiente rerum
exercitationem reprehenderit laborum eligendi cumque? Quia porro modi
repudiandae nostrum accusamus! Corporis eum fugit nihil facilis placeat
ab est obcaecati consequuntur qui atque tempore soluta aliquid saepe
ducimus, at sed modi illo ipsa numquam ratione vero eos reprehenderit!
Sapiente nesciunt consequatur labore iste quas possimus rem cumque,
fugit laborum repellendus nisi adipisci officia temporibus quaerat!
Beatae doloribus veritatis at, maiores suscipit debitis reiciendis cum
impedit non aut modi iste? Placeat illo quisquam assumenda esse cum
ipsum quasi perspiciatis voluptatem rerum itaque, similique quidem
molestias exercitationem ullam eum amet tempore dolor aliquid unde
deserunt dolore excepturi. Aut dolore rerum sequi nihil soluta eum
expedita consequatur aliquid consequuntur saepe esse necessitatibus
repudiandae, natus, officia enim odit rem nobis adipisci, voluptates
autem dolor blanditiis ipsam animi a. Illo accusantium iure qui aperiam
commodi, quidem, dolorem error eum animi, id nam? Corporis, non
adipisci!
)
}
当您想要跟踪特定 DOM 元素何时进入视图或何时消失时,此挂钩会很有用,例如,延迟加载图像、跟踪滚动位置或按需显示元素。
- 使用窗口大小
import { useState } from “react”
import useEventListener from “…/13-useEventListener/useEventListener”
export default function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
})
useEventListener(“resize”, () => {
setWindowSize({ width: window.innerWidth, height: window.innerHeight })
})
return windowSize
}
useWindowSize是一个自定义的 React 钩子,它允许组件跟踪浏览器窗口的当前大小。useState它使用React 库中的内置钩子和一个自定义钩子调用useEventListener,允许组件将事件侦听器添加到特定的DOM元素,并在事件发生时执行回调函数。
该挂钩创建一个名为windowSize的对象,其中包含浏览器窗口的宽度和高度,并使用window.innerWidth和window.innerHeight属性设置初始状态。
它使用useEventListener挂钩将调整大小事件侦听器添加到窗口对象,并在事件发生时使用窗口的新宽度和高度更新状态。
它返回windowSize对象,其中包含浏览器窗口的当前宽度和高度。
下面是一个如何使用这个钩子的例子:
import useWindowSize from “./useWindowSize”
export default function WindowSizeComponent() {
const { width, height } = useWindowSize()
return (
{width} x {height}
)
}
当您想要进行响应式设计并根据浏览器窗口的大小调整组件的布局或行为时,此挂钩会很有帮助。
结论
在制作良好的可扩展且无错误的项目时,这些自定义挂钩可能是必不可少的。他们工作起来很有魅力,即使在重要的项目上也是如此。因此,请随时在需要时使用它们。所以,感谢你们阅读这篇文章,伙计们。我知道这有点冗长。但是,我希望它值得一读。我们下一篇文章再见😊。
本文介绍了15个实用的React自定义钩子,包括使用切换、超时、去抖动等功能,帮助开发者提高代码复用性和可维护性。每个钩子都有详细的使用示例,涵盖了状态管理、异步处理和事件监听等多个场景,旨在提升React应用的开发效率。

被折叠的 条评论
为什么被折叠?



