面试官:自定义一个React hook,用于监听组件的重新渲染

写在前面

笔者最近看到这样一道面试题,如题目所示,觉得挺有意思的,在这里分享一下,感兴趣的小伙伴也可以思考一下怎么实现,可以在评论区讨论一下,我再详细说一下什么意思。

自定义一个 hook,如果监听到组件重新渲染,则在当前页面进行响应。(首次加载组件不执行)

思考

我们可以先想一下,如果不自定义钩子函数,如何监听组件的重新渲染?

我们知道在 react 中,当依赖发生变化时,会重新渲染组件,那我们可以结合 useEffect 添加依赖项,这样当依赖变化时,就可以监听到了。

代码如下:

js 复制代码
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 的依赖项不存在时,会在组件重现渲染时执行,而不依赖于任何依赖项变化。

js 复制代码
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 属性可以在组件的整个生命周期内保持不变,即使组件重新渲染。

js 复制代码
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。

实现

现在只需要接收一个函数,用于监听到变化时执行我们需要的逻辑即可。

js 复制代码
//useEffectOnUpdate.js
import { useEffect, useRef } from 'react';
export const useEffectOnUpdate = (effect) => {
  const isMounted = useRef(false);

  useEffect(() => {
    if (isMounted.current) {
      effect();
    } else {
      isMounted.current = true;
    }
  });
};

页面中使用

js 复制代码
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 依赖项不同情况的理解,包括有依赖项依赖项为空数组无依赖项三种情况。

相关推荐
前端不太难7 小时前
从 Navigation State 反推架构腐化
前端·架构·react
前端程序猿之路7 小时前
Next.js 入门指南 - 从 Vue 角度的理解
前端·vue.js·语言模型·ai编程·入门·next.js·deepseek
大布布将军8 小时前
⚡️ 深入数据之海:SQL 基础与 ORM 的应用
前端·数据库·经验分享·sql·程序人生·面试·改行学it
川贝枇杷膏cbppg8 小时前
Redis 的 RDB 持久化
前端·redis·bootstrap
D_C_tyu8 小时前
Vue3 + Element Plus | el-table 表格获取排序后的数据
javascript·vue.js·elementui
JIngJaneIL8 小时前
基于java+ vue农产投入线上管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
天外天-亮9 小时前
v-if、v-show、display: none、visibility: hidden区别
前端·javascript·html
jump_jump9 小时前
手写一个 Askama 模板压缩工具
前端·性能优化·rust
be or not to be9 小时前
HTML入门系列:从图片到表单,再到音视频的完整实践
前端·html·音视频
90后的晨仔9 小时前
在macOS上无缝整合:为Claude Code配置魔搭社区免费API完全指南
前端