useEventListener 事件监听的 customHook
- 定义custom hook时名字
必须以use开头,否则eslint会报错,因为不管是自己定义的hook还是react自带的hook都只能在组件中或其他hook中运行, 需要在顶层调用
const useEventListener(eventName, handler, element = window) => {
// 创建一个存储处理程序的引用
const savedHandler = useRef();
// 如果依赖 [handler] 发生更改,则更新ref.current值.
// 这使得我们下面的效果总是得到最新的处理程序
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(
() => {
const isSupported = element && element.addEventListener;
if (!isSupported) return;
// 创建调用ref中存储的处理程序函数的事件侦听器
const eventListener = event => savedHandler.current(event);
// Add 监听事件
element.addEventListener(eventName, eventListener);
// 销毁时移除监听
return () => {
element.removeEventListener(eventName, eventListener);
};
},
[eventName, element],
);
}
useEventListener('click', function() {
// todo something
})
useMount 的 customHook 封装useEffect
export const useMount = (callback) => {
useEffect(() => {
callback()
},[])
}
// 只在页面渲染时执行一次获取data
useMount(() => {
fetch(`${Url}/data`).then(async response => {
if (response.ok) {
setUsers(await response.json())
}
})
})
useComponentWillMount 自定义hook 类组件生命周期 ComponentWillMount
const useComponentWillMount = func => {
const willMount = useRef(true);
if (willMount.current) {
func();
}
willMount.current = false;
};
useDebounce 的 customHook, 多用在 input 搜索框的调用API
- 定义
搜索框防抖debounce,只会执行最后的定时任务 节流是同一时间只能执行一个任务,执行完毕后才能执行下一个,原理是定义一个状态,在执行任务前后改变状态,执行体通过判断此状态可以判断该函数是否在执行,从而决定是否执行
多用在 input 搜索框
// 防抖示例
export const debounce = (func, delay) => {
let timeout
return ()=> {
if(timeout){
clearTimeout(timeout)
}
timeout = setTimeout(() => {
func()
}, delay);
}
}
export const useDebounce = (value, delay) => {
const [debounceValue, setDebounceValue] = useState(value)
// 每当输入框传入的value变化时,Effect hook就会设置一个定时器,
// 在delay时间后操作state hook更新从外界传入的debounceVlue中的value值,
// 当此定时器执行完毕后 Effect再清理定时器 最后将处理后的value return出去
useEffect(() => {
const timeout = setTimeout(() => setDebounceValue(value), delay)
return () => clearTimeout(timeout)
}, [value, delay])
return debounceValue
}
每次value更新,就会重新触发下一个useEffect,这时就会执行return里的函数,
意思就是每个useEffect触发时,将会清理掉上一个useEffect定义的定时器
例子:请求 API 时
const debounceParam = useDebounce(param, 2000)
useEffect(() => {
//请求接口
fetch(`${api}/user?${qs.stringify(debounceParam)}`)
.then(async response => {
if (response.ok) {
// json()返回一个为JSON格式的promise对象
setList(await response.json())
}
})
}, [debounceParam])
自定义hook useData 获取API数据,异步获取数据的封装
- blog.csdn.net/qdmoment/ar…
- 1 接收 url, query
- 2 返回 data,isLoading, isError,setQuery
// 调用
const [ data, setQuery, isLoading ] = useData(url)
function useData(url, options = {}) {
const [query, setQuery] = useState({});
const [ data, setData ] = useState(null);
const [isLoading, setLoading ] = useState(false);
const [isError, setError ] = useState(false)
useEffect( () => {
async function fetchData(){
try{
let res = await ApiConfig.usual.useData(url,query)
console.log(res)
if(res.status == '200'){
setData(res.data)
}
} catch(err){
console.log(err)
setError(true)
}
setLoading(false)
}
setLoading(true)
fetchData()
}, [url,query])
return [ data, setQuery, isLoading, isError ]
}
useEffect中请求API,可以主动中断请求
- abortController =
new AbortController(),主动的方式是探知到卸载时直接中断请求,不必再收到响应时进行判断 AbortController是一个浏览器的实验接口,它可以返回一个信号量(singal),从而中止发送的请求- 链接 :技术来源CSDN
useEffect(() => {
let isUnmounted = false;
const abortController = new AbortController(); // 创建
(async () => {
const res = await fetch(SOME_API, {
singal: abortController.singal, // 当做信号量传入
});
const data = await res.json();
if (!isUnmounted) {
setValue(data.value);
setLoading(false);
}
})();
return () => {
isUnmounted = true;
abortController.abort(); // 在组件卸载时中断
}
}, []);
结语
前端react QQ群:
788023830----React/Redux - 地下老英雄前端交流 QQ群:
249620372----FRONT-END-JS前端(我们的宗旨是,为了加班,为了秃顶……,仰望大佬),希望小伙伴们加群一起学习