写在前面
作者最近看到这样一道面试题,如题目所示,觉得挺有意思,感兴趣的小伙伴也可以思考一下怎么实现,可以在评论区讨论一下,我再详细说一下什么意思。
自定义一个 hook,如果监听到组件重新渲染,则在当前页面进行响应。(首次加载组件不执行)
思考
我们可以先想一下,如果不自定义钩子函数,如何监听组件的重新渲染?
我们知道在 react 中,当依赖发生变化时,会重新渲染组件,那我们可以结合 useEffect 添加依赖项,这样当依赖变化时,就可以监听到了。
代码如下:
function Demo() {
const [count, setCount] = useState(0)
useEffect(() => {
console.log('依赖为[count]------------------------', count)
}, [count])
return (
<div>
<p>count的值为: {count} </p>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
)
}
但是这样写的弊端在于,useEffect 只会在依赖变化时重新渲染,如果我们组件中还有其他依赖发生变化,就监听不到了。
所以我们可以不写 useEffect 的依赖项,当 useEffect 的依赖项不存在时,会在组件重现渲染时执行,而不依赖于任何依赖项变化。
function Demo() {
const [count, setCount] = useState(0)
useEffect(() => {
console.log('无依赖为[count]------------------------', count)
})
return (
<div>
<p>count的值为: {count} </p>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
)
}
但是这样会在组件第一次进入也执行,我们只希望组件重新渲染时执行,增加判断条件即可。
使用 useRef
返回的对象的 .current
属性可以在组件的整个生命周期内保持不变,即使组件重新渲染。
function Demo() {
const [count, setCount] = useState(0)
const isMounted = useRef(false)
useEffect(() => {
if (isMounted.current) {
//执行代码
} else {
isMounted.current = true;
}
})
return (
<div>
<p>count的值为: {count} </p>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
)
}
这样只会在页面重新渲染时执行这个useEffect,现在我们把它封装成 hook。
实现
现在只需要接收一个函数,用于监听到变化时执行。
//useEffectOnUpdate.js
import { useEffect, useRef } from 'react';
export const useEffectOnUpdate = (effect) => {
const isMounted = useRef(false);
useEffect(() => {
if (isMounted.current) {
effect();
} else {
isMounted.current = true;
}
});
};
页面中使用
import { useEffectOnUpdate } from '../hook/useEffectOnUpdate'
import React, { useEffect, useState } from 'react'
// 使用示例
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffectOnUpdate(() => {
console.log('Component updated!');
});
return (
<div>
<p>count的值为: {count} </p>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
)
};
总结
我们在实现的时候可以先想一下,如果不是封装 hook,在组件内实现应该怎么做,进而将思路理清,然后将实现的代码再转化为 hook 即可。
在这个案例中,需要理解 useEffect 的使用,主要是对 useEffect 依赖项不同情况的理解,包括有依赖项,依赖项为空数组,无依赖项三种情况。