前言
随着react16.8的公布,hook新个性随之而来,hook的到来让function组件焕发出弱小的能力,足矣取代之前的class组件。函数式组件依附useState、useEffect等hook实现变量状态维持、抽离副作用等性能。尽管原生的useEffect具备弱小的性能,然而那些罕用的写法每次都要手动复现一次,岂但影响开发效率,而且容易出错。
上面我会给大家举荐一个npm第三方库,它将与无关useEffect罕用的写法都封装起来,相对能够助力你的开发,
让你的开发蛟龙得水。
这个库的名称是pluto-hooks,在npm官网上也能够搜寻到其相干信息,上面是npm地址
https://www.npmjs.com/package...
此我的项目大部分hook都是和useEffect无关,当然也有其余,开发者们能够自行抉择应用,上面介绍一下此库的应用办法
装置
首先先要在react我的项目中装置,举荐应用yarn装置
yarn
yarn add pluto-hooks
npm
npm i pluto-hooks
应用
在react我的项目中间接援用即可
import { useEffectOnece } from "pluto-hooks";useEffectOnece(() => { console.log("触发");});
前置常识
要理解上面的用法,你得对react组件(这里只用函数式组件)及hook有一些理解
什么时候会触发组件渲染
组件中的状态扭转的时候,
- useState扭转状态
- 子组件调用父组件的办法使父组件的状态扭转
- props扭转
- 父组件从新渲染
- 生成该组件的工厂函数从新执行(如改工厂函数放在useCallback中,依赖值发生变化)
useEffect的两个参数
effect
该参数接管一个函数,该函数返回一个销毁函数(指return返回的cleanup函数),如果 useEffect 第一个参数传入 async,返回值则变成了 Promise,会导致 react 在调用销毁函数的时候报错 :function.apply is undefined
deps
改参数接管一个数组,数组中寄存useEffect的依赖值,当页面从新渲染时react会比照前一个deps和新deps,这里是用的浅比拟对deps中的每个元素进行比拟,所以当
deps=[{}]
时effect每次都会执行,因为{} !=== {}
hooks介绍
useCountUpdateEffect
第n次渲染并且deps变动才执行effect
有时候咱们在我的项目开发中须要在组件渲染到固定次数时触发某个办法,如应用input输出文本时,每次敲击键盘都会触发一次render,咱们能够应用useCountUpdateEffect
管制effect的触发机会
注:第一次渲染也算一次
示例
import React, { useState } from "react";import useCountUpdateEffect from "../index";export default () => { const [text, setText] = useState(''); function inputChange(e){ setText(e.target.value) } useCountUpdateEffect(() => { console.log('useCountUpdateEffect执行'); },10); return ( <div> <p>{text}</p> <p> <input type="text" onChange={inputChange} /> </p> </div> );};
useRangeUpdateEffect
在组件渲染次数为[range[0],range[1]]之间执行
此hook为useCountUpdateEffect
的升级版,有时候咱们不肯定要在某个渲染次数时触发回调函数,而是要在某个范畴内间断触发
其中第二个参数传入一个数组range,range[0]为左边界,range[1]为右边界,若传入[,right]
,则默认为[0,right]
,如果传入[left,]
,则大于left(包含left)的渲染次数都会触发effect,若传入[]
,则与useEffect
没有区别
第三个参数为依赖deps
示例
import React, { useState } from "react";import useRangeUpdateEffect from "../index";export default () => { const [text, setText] = useState(''); function inputChange(e){ setText(e.target.value) } useRangeUpdateEffect(() => { console.log('useRangeUpdateEffect'); },[5,10]); return ( <div> <p>{text}</p> <p> <input type="text" onChange={inputChange} /> </p> </div> );};
同样的,这里也会算上初始渲染,如果想不思考首次渲染,能够调整第二个参数的范畴
useCompareEffect
type { effect:EffectCallback, deps:DependencyList, depsEqual:(oldDeps:DependencyList,nextDeps:DependencyList) => boolean}
正如咱们前置常识讲到的,useEffect默认只会对deps进行浅比拟,然而应用useCompareEffect
咱们就能够自定义deps的比拟
第三个参数为比拟函数,depsEqual的第一个参数是旧的deps数组,第二个参数为新的deps数组,该函数返回一个boolean值,为true时不执行effect,反之执行
示例
import React, { useState } from "react";import useCompareEffect from "../index"export default function demo() { const [count1, setCount1] = useState(0) const [count2, setCount2] = useState(0) const [count, setCount] = useState(0) const compareFn = (old,next) => { console.log('old,next: ', old,next); return old[1] === next[1] } useCompareEffect(() => { // 只有count2扭转时会触发 setCount(state => state + 1) }, [count1, count2],compareFn) return ( <div> <h2>{count}</h2> <h2>{count1}</h2> <h2>{count2}</h2> <button onClick={() => {setCount1(state => state + 1)}}>count1</button> <button onClick={() => {setCount2(state => state + 1)}}>count2</button> </div> )}
useDeepCompareEffect
此hook基于下面的useCompareEffect
,当组件从新渲染时执行useDeepCompareEffect,该hook将对deps进行深比拟,若相等则执行effect
type { effect:EffectCallback, deps:DependencyList,}
useAsyncEffect
看过前置常识的小伙伴可能还记得,useEffect的第一个参数是不能传入async函数的,如果真的要应用async函数,能够调用useAsyncEffect
示例
import React, { useState } from "react";import useAsyncEffect from "../index"export default () => { const fn = () => { return new Promise(resolve => { setTimeout(() => { resolve() }, 3000) }) } useAsyncEffect(async () => { console.log('期待...'); await fn() console.log('实现'); }, []);};
以上代码将会在组件初始化时显示”期待...“,3秒后显示”实现“
useDebounceFn
解决防抖函数
const { run, cancel, flush} = useDebounceFn( fn: (...args: any[]) => any, options?: Options);
run, cancel, flush为可执行函数
run:开始防抖地执行fn,传入run的参数会传到fn
cancel:勾销执行fn
flush:立刻执行fn,不必等到wait工夫完结
useDebounceEffect
type { effect:EffectCallback, deps?:DependencyList, options:DebounceOptions}
将传入的Effect带上防抖,options能够配置防抖参数
options参数(默认值):
[options.wait=1000] (number): 等待时间,单位为毫秒。[options.leading=false] (boolean): 指定在提早开始前调用。[options.maxWait] (number): 设置 func 容许被提早的最大值。[options.trailing=true] (boolean): 指定在提早完结后调用。
useThrottleFn
解决节流函数的hook
const { run, cancel, flush} = useThrottleFn( fn: (...args: any[]) => any, options?: Options);
options参数:
[options.wait=1000] (number): 等待时间,单位为毫秒。[options.leading=true] (boolean): 指定调用在节流开始前。[options.trailing=true] (boolean): 指定调用在节流完结后。
run, cancel, flush为可执行函数
run:开始防抖地执行fn,传入run的参数会传到fn
cancel:勾销执行fn
flush:立刻执行fn,不必等到wait工夫完结
useThrottleEffect
将传入的Effect带上节流性能,options能够配置节流参数
type { effect:EffectCallback, deps:DependencyList, options:ThrottleOptions}
options参数:
[options.wait=1000] (number): 等待时间,单位为毫秒。[options.leading=true] (boolean): 指定调用在节流开始前。[options.trailing=true] (boolean): 指定调用在节流完结后。
useEffectOnce
只在第一次渲染时执行
type { effect:EffectCallback,}
useFirstMountState
判断改选件是否是第一次渲染,返回Boolean
示例
import React, { useEffect, useState } from "react";import useFirstMountState from "../index"export default () => { const [count, setCount] = useState(0); const isfirst = useFirstMountState() console.log('isfirst: ', isfirst); return ( <div> <div>first:{isfirst}</div> <p> <button type="button" onClick={() => setCount((c) => c + 1)}> reRender </button> </p> </div> )}
能够看到前面点击reRender时useFirstMountState()
都是返回false
useUpdateEffect
非首次渲染时执行
type { effect:EffectCallback, deps:DependencyList,}
对这个我的项目的介绍就到这里啦,如果前面有更新会持续的,此我的项目的github地址https://github.com/plutoLam/h...,应用bruce-app搭建,rollup进行打包