因此,当Child被memo包装后,就只会当props改变时才会重新渲染了。
当然,由于React.memo并不是react-hook的内容,所以这里并不会取讨论它是怎么实现的。
useCallback的使用
当我们试图给一个子组件传递一个方法的时候,如下代码所示
import React ,{useState,memo}from ‘react’;
import ReactDOM from ‘react-dom’;
function Child({data}) {
console.log(“天啊,我怎么被渲染啦,我并不希望啊”)
return (
)
}
// 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 (
)
}
// 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 (
)
}
当依赖项有值改变的时候,我们需要对lastCallback和lastCallbackDependencies重新赋值
import React ,{useState,memo}from ‘react’;
import ReactDOM from ‘react-dom’;
let lastCallback
// eslint-disable-next-line
let lastCallback