React常用自定义Hook
自定义Hook
useDebounce
防抖
1
2
3
4
5
6
7
8
9
10
11
12
13
14import { useState, useEffect } from 'react'
function useDebounce(value: any, delay = 300) {
const [debouncedValue, setDebouncedValue] = useState(value)
useEffect(() => {
const handler = window.setTimeout(() => {
setDebouncedValue(value)
}, delay)
return () => {
clearTimeout(handler)
}
}, [value, delay])
return debouncedValue
}
export default useDebounce;使用方式
1
2
3import useDebounce from './useDebounce'
const useDebounceValue = useDebounce(inputValue, 500)
// 此时只要 把 之前的 表单value 全部换成 useDebounceValue就行了
useThrottle
- 节流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import {useEffect, useRef,useCallback} from 'react';
function useThrottle(fn, delay, dep = []) {
const { current } = useRef({ fn, timer: null });
useEffect(function () {
current.fn = fn;
}, [fn]);
return useCallback(function (...args) {
if (!current.timer) {
current.timer = setTimeout(() => {
delete current.timer;
}, delay);
current.fn.call(this, ...args);
}
}, dep);
}
export default useThrottle - 使用方式
1
2import useThrottle from './useThrottle'
const throttledFunc = useThrottle(fn, 2000);
useVirtualList
虚拟列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44// 虚拟列表
import { RefObject, useEffect, useState } from 'react'
interface Args extends IntersectionObserverInit {
freezeOnceVisible?: boolean
}
/**
*
* @param {ReactRef} elementRef 传入虚拟列表父盒子的 ref
* @param {object}
* threshold 阀值 0-1 1表示完全出现在屏幕可视区域才触发
* root 表示指定根元素 默认为浏览器视口 用于检查目标可见性
* rootMargin root的外边距 '0 0 0 0'
* freezeOnceVisible 是否缓存 再次滑动不重新渲染
* @returns {Object} entry 这个对象具有当前可视区的信息
* 例如 entry.isIntersecting 是否在可视区范围
*/
function useVirtualList(
elementRef: RefObject<Element>,
{
threshold = 0,
root = null,
rootMargin = '0%',
freezeOnceVisible = false
}: Args
): IntersectionObserverEntry | undefined {
const [entry, setEntry] = useState<IntersectionObserverEntry>()
const frozen = entry?.isIntersecting && freezeOnceVisible
const updateEntry = ([entry]: IntersectionObserverEntry[]): void => {
setEntry(entry)
}
useEffect(() => {
const node = elementRef?.current
const hasIOSupport = !!window.IntersectionObserver
if (!hasIOSupport || frozen || !node) return
const observerParams = { threshold, root, rootMargin }
const observer = new IntersectionObserver(updateEntry, observerParams)
observer.observe(node)
return () => observer.disconnect()
}, [elementRef, JSON.stringify(threshold), root, rootMargin, frozen])
return entry
}
export default useVirtualList使用方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30// 只要判断entry是true还是false就可以得知 他是不是在可视区了
const Section = (props) => {
const ref = useRef(null)
const entry = useVirtualList(ref, {})
// !! 将它转成布尔值
const isVisible = !!entry?.isIntersecting
console.log(`Render Section ${props.title}`, { isVisible })
return (
<div
ref={ref}
style={{
minHeight: '100vh',
display: 'flex',
border: '1px dashed #000',
fontSize: '2rem',
width: '100%'
}}
>
{
isVisible ? (
<div style={{ margin: 'auto' }}>{props.title}</div>
) : ""
}
</div>
)
}
Array.from({ length: 100 }).map((_, index) => (
<Section key={index + 1} title={`${index + 1}`} />
))
useScrollPostion
1 | // 获取滚动条高度 |
- 使用方式
1
2import useScrollPostion form './useScrollPostion'
const position = useScrollPostion()
useWinSize
1 | // 获取屏幕尺寸 |
- 使用方式
1
2import useWinSize form './useWinSize'
const size = useWinSize()
useIsVisible
1 | // 是否在可视区 |
- 使用方式
1
2
3
4const elemRef = useRef();
const isVisible = useVisible(elemRef);
<div style={{ height: "145vh", width: '100%' }}>1</div>
<div ref={elemRef}>hello {isVisible && console.log("visible")}</div>
forceUpdate
1 | const [ignored, forceUpdate] = useReducer(x => x + 1, 0); |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LiuYuanhua!
评论