开发中经常会遇到一些通用功能,我们可以将其逻辑抽取出,封装成通用函数,以方便后续使用,避免重复开发,便于维护。
下面是一些基础函数示例。
useAsync
useUpdate
const incrementParameter=num=>++num;
const useUpdate=()=>{
const [,setState]=useState(0);
return useCallback(()=>setState(incrementParameter),[]);
};
useCancelablePromise
const useCancelablePromise=(deps=[])=>{
const promises=useRef([]);
useEffect(()=>{
return ()=>{
promises.current.map(fn=>fn.cancelFn());
promises.current=[];
};
},deps);
const cancellablePromise=(fn,delay=true)=>{
const wrapPromise=cancelablePromise(fn,delay);
if(promises.current.indexOf(wrapPromise)===-1){
promises.current.push(wrapPromise);
}
return wrapPromise.promiseFn;
};
return {cancellablePromise};
};
useRaf
const useRaf=initialState=>{
const frame=useRef(0);
const [state,setState]=useState(initialState);
const setRaf=useCallback(value=>{
cancelAnimationFrame(frame.current);
frame.current=requestAnimationFrame(()=>{
setState(value);
});
},[]);
useEffect(()=>{
return ()=>cancelAnimationFrame(frame.current);
},[]);
return [state,setRaf];
};
useScroll
const useScroll=(element=null)=>{
const [state,setRaf]=useRaf(getOffset(element));
const handler=useCallback(()=>setRaf(getOffset(element)),[element]);
useEffect(()=>{
const listener=isElement(element)?element:window;
listener.addEventListener('scroll',handler,{capture:false,passive:true});
return ()=>listener.removeEventListener('scroll',handler);
},[handler]);
return state;
};
useSearch
const useSearch=(initState,hlResult=toDom)=>{
const [state,setState]=useState(initState);
const setList=useCallback((...args)=>{
const [data,keyword,...rest]=args;
if(!keyword){
setState(null);
}else{
args=[data,keyword,hlResult,...rest];
const newList=filterList(...args);
setState(newList);
}
},[]);
return [state,setList];
};
useWinResize
const useWinResize=()=>{
const [state,setRaf]=useRaf(getViewportSize());
const handler=useCallback(()=>setRaf(getViewportSize()),[]);
useEffect(()=>{
window.addEventListener('resize',handler,false);
return ()=>window.removeEventListener('resize',handler,false);
},[handler]);
return state;
};
useEleResize
const useEleResize=(element=null)=>{
const {bind,destroy}=resize(element);
const [state,setRaf]=useRaf(getViewportSize(element));
const handler=useCallback(()=>setRaf(getViewportSize(element)),[element]);
useEffect(()=>{
bind(handler);
return ()=>destroy();
},[handler]);
return state;
};
useClickAway
const useClickAway=(ref,handleEvent,events='click')=>{
const handler=useCallback(event=>{
const el=ref?.current??ref;
if(el&&!el.contains(event.target)){
handleEvent(event);
}
},[ref,handleEvent]);
useEffect(()=>{
document.addEventListener(events,handler,false);
return ()=>{
document.removeEventListener(events,handler,false);
};
},[events,handler]);
};
useDebounce
const useDebounce=(fn,delay)=>useMemo(()=>debounce(fn,delay),[delay]);