何为hooks?
在React中hook是指不编写 class 的情况下使用 state 以及其他的 React 特性,而Vue3也推出了具有相同功能的组合式API。如果你用过Vue3就会知道在 setup 中你应该避免使用 this,因为hook的核心功能是让我们在脱离 React,Vue的情况下任然可以使用computed,watch,数据更改视图响应等功能。
所以以下hook在Vue,React中是可以实现的
useDebounce
import { useState, useEffect } from "react";
const useDebounce = (value, delay) => {
const [state, setState] = useState(value);
useEffect(() => {
const timeout = setTimeout(() => {
setState(value)
}, delay)
return () => clearTimeout(timeout)
}, [value, delay])
return state
}
export default useDebounce
const [state, setState] = useState('')
const debounceState = useDebounce(state)
防抖函数,这在表单输入时特别有用
useThrottle
Throttle实现起来就比Debounce复杂的多,在笔者之前的博客中曾经多次提到过,对于复杂的实现可以先吧函数架子搭起来。
const useThrottle = (initialState, fps) => {
return [state, useThrottleCallback]
}
拆解一下首先参数initialState初始值,fsp则是间隔调用的时间。 返回值上useThrottleCallback就是setState,不管外部调用的多么频繁useThrottleCallback始终根据fps的间隔调用。 这样就明确了参数和返回值
const useThrottle = (initialState, fps) => {
const [state, setState] = useState(initialState)
const useThrottleCallback = throttle(setState, fps)
return [state, useThrottleCallback]
}
使用如下
const [state, useThrottleCallback] = useThrottle('', 200)
这么写的话是错误的,由于state每次更新都会重新触发render函数,从而导致内部的throttle也不断的重新创建了,而throttle内部某些基于闭包的变量也因为重新创建而失去了原本的作用。 改造如下,基于useRef保存时间变量
const useThrottleCb = (fn, wait) => {
let previous = useRef(0)
return (...args) => {
let now = +new Date()
if (now - previous.current > wait) {
previous.current = now
fn.apply(null, args)
}
}
}
const useThrottleCallback = useThrottleCb(setState, fps)
useTodos
接下来看一下如何用一个hook实现具有增删清空的todo项目
interface IuseTodos<T> {
todos: T[];
addTD : (todo: T) => void;
removeTD : (index: number) => void;
clearTD : () => void;
}
const useTodos = <T>(initTD: T[]): IuseTodos<T> => {
const [todos, setTodos] = useState<T[]>(initTD)
const addTD = (todo: T) => setTodos([...todos, todo]);
const removeTD = (index: number) => {
const newTodos = [...todos];
newTodos.splice(index, 1)
setTodos(newTodos)
}
const clearTD = () => setTodos([])
return {
todos,
addTD,
removeTD,
clearTD
}
}
这hook + ts实践起来也太香了吧[/dog]
总结
- custom-hook的返回值是不固定了,可像useDebounce这样返回state而不提供setState,也可以像useThrottle返回一个标准的Tuple,也可以像useTodos返回多个方法。
- hook并不是非要围绕state的,完全可以利用hook封装一些工具方法,比如useAsync,useHash,useCookie这些一听名字就知道是做什么的hook
|