react 常用hooks整理

react 常用hooks

一 hooks 之数据更新驱动
1.1 useState
const [ ①state , ②dispatch ] = useState(③initData)
① state,目的提供给 UI ,作为渲染视图的数据源。

② dispatchAction 改变 state 的函数,可以理解为推动函数组件渲染的渲染函数。

③ initData 有两种情况,第一种情况是非函数,将作为 state 初始化的值。第二种情况是函数,函数的返回值作为 useState 初始化的值。

useState 注意事项:

① 在函数组件一次执行上下文中,state 的值是固定不变的。

② 如果两次 dispatchAction 传入相同的 state 值,那么组件就不会更新。

③ 当触发 dispatchAction 在当前执行上下文中获取不到最新的 state, 只有再下一次组件 rerender 中才能获取到。

1.2 useReducer
useReducer 是 react-hooks 提供的能够在无状态组件中运行的类似redux的功能 api 。

const [ ①state , ②dispatch ] = useReducer(③reducer)
① 更新之后的 state 值。

② 派发更新的 dispatchAction 函数, 本质上和 useState 的 dispatchAction 是一样的。

③ 一个函数 reducer ,我们可以认为它就是一个 redux 中的 reducer , reducer的参数就是常规reducer里面的state和action, 返回改变后的state, 这里有一个需要注意的点就是:如果返回的 state 和之前的 state ,内存指向相同,那么组件将不会更新。

二 hooks 之执行副作用

2.1 useEffect
useEffect(()=>{
return destory
},dep)
useEffect第一个参数callback,返回的destory,destory作为下一次callback执行之前调用,用于清除上一次callback产生的副作用。

第二个参数作为依赖项,是一个数组,可以有多个依赖,依赖项改变,执行上一次callback返回的destory,和执行新的effect第一个参数callback

对于useEffect执行,React处理逻辑是产用异步调用,对于每一个effect的callback,React会向setTimeout回调函数一样,放入任务队列,等到主线程任务完成,DOM更新,js执行完成,视图绘制完毕,才执行。所以effect回调函数不会阻塞浏览器绘制视图。

useEffect(()=>{
   /* 请求数据 */
   getUserInfo(a).then(res=>{
       setUserMessage(res)
   })
   /* 定时器 延时器等 */
   const timer = setInterval(()=>console.log(666),1000)
   /* 操作dom  */
   console.log(div.current) /* div */
   /* 事件监听等 */
   window.addEventListener('resize', handleResize)
     /* 此函数用于清除副作用 */
   return function(){
       clearInterval(timer) 
       window.removeEventListener('resize', handleResize)
   }
/* 只有当props->a和state->number改变的时候 ,useEffect副作用函数重新执行 ,如果此时数组为空[],证明函数只有在初始化的时候执行一次相当于componentDidMount */
},[ a ,number ])

如上在useEffect中做的功能如下:

1、请求数据

2、设置定时器、延时器等。

3、操作dom,在 React Native 中可以通过 ref 获取元素位置信息等内容。

4、注册事件监听器,事件绑定,在React Native中可以注册NativeEventEmitter

5、清除定时器、延时器,解绑事件监听器等。

三 hooks 之状态获取与传递

3.1 useContext
1、可以使用useContext,来获取父级组件传递过来的context值,这个当前值就是最近的父级组件Provider设置的value值,useContext参数一般是由createContext方式创建,也可以是父级上下文context传递的。useContext可以代替context.Consumer来获取Provider中保存的value值。

const contextValue = useContext(context)
/* 用useContext方式 /
const DemoContext = ()=> {
const value:any = useContext(Context)
/
my name is alien /
return

my name is { value.name }

}

/ 用Context.Consumer 方式 /
const DemoContext1 = ()=>{
return <Context.Consumer>
{/
my name is alien */}
{ (value)=>
my name is { value.name }
}
</Context.Consumer>
}

export default ()=>{
return

<Context.Provider value={{ name:‘alien’ , age:18 }} >


</Context.Provider>

}

3.2 useRef
useRef可以用来获取元素,缓存状态,接受一个状态initState作为初始值,返回一个ref对象cur,cur上有一个current属性就是ref对象需要获取的内容

const cur = React.useRef(initState)
useRef 获取 DOM 元素

const DemoUseRef = ()=>{
const dom= useRef(null)
const handerSubmit = ()=>{
/*

表单组件
dom 节点 /
console.log(dom.current)
}
return

{/ ref 标记当前dom节点 */}
表单组件

<button onClick={()=>handerSubmit()} >提交

}
useRef 保存状态, 可以利用 useRef 返回的 ref 对象来保存状态,只要当前组件不被销毁,那么状态就会一直存在。

const status = useRef(false)
/* 改变状态 */
const handleChangeStatus = () => {
status.current = true
}

四 hooks 之状态派生与保存

4.1 useMemo
useMemo可以在函数组件render上下文中同步执行一个函数逻辑,这个函数的返回值可以作为一个新的状态缓存起来。

应用场景:1、在一些场景下,需要在函数组件中进行大量的逻辑计算,那么我们不期望每一次函数组件渲染都执 行这些复杂的计算逻辑,所以在useMemo的回调函数中执行这些逻辑,然后把得到的计算结果缓存起 来就可以了。

2、React在整个更新流程中,diff起到了决定性的作用,比如Context中的provider通过diff value来判 断是否更新

const cacheSomething = useMemo(create,deps)
① create:第一个参数作为一个函数,函数的返回值作为缓存值,如上demo中把children对应的element对象,缓存起来。

② deps:第二个参数作为一个数组,存放当前useMemo的依赖项,在函数组件下一次执行的时候,会对比deps依赖项里面的状态,是否有改变,如果有改变重新执行create,得到新的缓存值。

③ acheSomething:执行create的返回值。如果deps中的依赖项有改变,返回的重新执行create产生的值,否之取上一次的缓存值。

/* 通过 useMemo 得到派生出来的新状态 contextValue  */
const contextValue = useMemo(() => {
    return {
        cacheDispatch: cacheDispatch.bind(keeper),
        hasAliveStatus: hasAliveStatus.bind(keeper),
        cacheDestory: (payload) => cacheDispatch.call(keeper, { type: ACTION_DESTORY, payload })
    }
  
}, [keeper])


缓存计算结果:

function Scope(){
const style = useMemo(()=>{
let computedStyle = {}
// 经过大量的计算
return computedStyle
},[])
return


}
缓存组件,减少子组件 rerender 次数:

function Scope ({ children }){
const renderChild = useMemo(()=>{ children() },[ children ])
return

{ renderChild }

}
4.2 useCallback
useMemo和useCallback接收的参数都一样,都是在其依赖项发生改变后才执行,都是返回缓存的值,区别在于useMemo返回的是函数执行的结果,useCallback返回的是函数,这个回调函数是经过处理之后的也就是说父组件传递一个函数给子组件的时候,由于是无状态组件每一次都会重新生成新的props函数,这样就使得每一次传递给子组件的函数都发生了变化,这时候就会触发子组件的更新,这些更新是没有必要的,此时我们就可以通过usecallback来处理此函数,然后作为props传递给子组件。

/* 用react.memo /
const DemoChildren = React.memo((props)=>{
/
只有初始化的时候打印了 子组件更新 /
console.log(‘子组件更新’)
useEffect(()=>{
props.getInfo(‘子组件’)
},[])
return

子组件

})

const DemoUseCallback=({ id })=>{
const [number, setNumber] = useState(1)
/ 此时usecallback的第一参数 (sonName)=>{ console.log(sonName) }
经过处理赋值给 getInfo /
const getInfo = useCallback((sonName)=>{
console.log(sonName)
},[id])
return

{/ 点击按钮触发父组件更新 ,但是子组件没有更新 */}
<button onClick={ ()=>setNumber(number+1) } >增加


}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值