手写ReactHook核心原理,再也不怕面试官问我ReactHook原理

因此,当Child被memo包装后,就只会当props改变时才会重新渲染了。

当然,由于React.memo并不是react-hook的内容,所以这里并不会取讨论它是怎么实现的。

手写useCallback


useCallback的使用

当我们试图给一个子组件传递一个方法的时候,如下代码所示

import React ,{useState,memo}from ‘react’;

import ReactDOM from ‘react-dom’;

function Child({data}) {

console.log(“天啊,我怎么被渲染啦,我并不希望啊”)

return (

child

)

}

// eslint-disable-next-line

Child = memo(Child)

function App(){

const [count, setCount] = useState(0);

const addClick = ()=>{console.log(“addClick”)}

return (

<button onClick={() => { setCount(count + 1)}}>

增加

);

}

function render(){

ReactDOM.render(

,

document.getElementById(‘root’)

);

}

render()

发现我们传了一个addClick方法 是固定的,但是却每一次点击按钮子组件都会重新渲染。

这是因为你看似addClick方法没改变,其实旧的和新的addClick是不一样的,如图所示

在这里插入图片描述

这时,如果想要,传入的都是同一个方法,就要用到useCallBack。

如代码所示

import React ,{useState,memo,useCallback}from ‘react’;

import ReactDOM from ‘react-dom’;

function Child({data}) {

console.log(“天啊,我怎么被渲染啦,我并不希望啊”)

return (

child

)

}

// eslint-disable-next-line

Child = memo(Child)

function App(){

const [count, setCount] = useState(0);

// eslint-disable-next-line

const addClick = useCallback(()=>{console.log(“addClick”)},[])

return (

<button onClick={() => { setCount(count + 1)}}>

增加

);

}

function render(){

ReactDOM.render(

,

document.getElementById(‘root’)

);

}

render()

useCallback钩子的第一个参数是我们要传递给子组件的方法,第二个参数是一个数组,用于监听数组里的元素变化的时候,才会返回一个新的方法。

原理实现

我们知道useCallback有两个参数,所以可以先写

function useCallback(callback,lastCallbackDependencies){

}

跟useState一样,我们同样需要用全局变量把callback和dependencies保存下来。

let lastCallback

let lastCallbackDependencies

function useCallback(callback,dependencies){

}

首先useCallback会判断我们是否传入了依赖项,如果没有传的话,说明要每一次执行useCallback都返回最新的callback

let lastCallback

let lastCallbackDependencies

function useCallback(callback,dependencies){

if(lastCallbackDependencies){

}else{ // 没有传入依赖项

}

return lastCallback

}

所以当我们没有传入依赖项的时候,实际上可以把它当作第一次执行,因此,要把lastCallback和lastCallbackDependencies重新赋值

let lastCallback

let lastCallbackDependencies

function useCallback(callback,dependencies){

if(lastCallbackDependencies){

}else{ // 没有传入依赖项

lastCallback = callback

lastCallbackDependencies = dependencies

}

return lastCallback

}

当有传入依赖项的时候,需要看看新的依赖数组的每一项和来的依赖数组的每一项的值是否相等

let lastCallback

let lastCallbackDependencies

function useCallback(callback,dependencies){

if(lastCallbackDependencies){

let changed = !dependencies.every((item,index)=>{

return item === lastCallbackDependencies[index]

})

}else{ // 没有传入依赖项

lastCallback = callback

lastCallbackDependencies = dependencies

}

return lastCallback

}

function Child({data}) {

console.log(“天啊,我怎么被渲染啦,我并不希望啊”)

return (

child

)

}

当依赖项有值改变的时候,我们需要对lastCallback和lastCallbackDependencies重新赋值

import React ,{useState,memo}from ‘react’;

import ReactDOM from ‘react-dom’;

let lastCallback

// eslint-disable-next-line

let lastCallbackDependencies

function

  • 28
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值