面试官:自定义一个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 依赖项不同情况的理解,包括有依赖项依赖项为空数组无依赖项三种情况。

相关推荐
我的xiaodoujiao13 分钟前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 25--数据驱动--参数化处理 Excel 文件 2
前端·python·学习·测试工具·ui·pytest
San30.15 分钟前
从代码规范到 AI Agent:现代前端开发的智能化演进
javascript·人工智能·代码规范
岁月宁静40 分钟前
从0到1:智能汇 AI 全栈实战,拆解多模态 AI 应用开发全流程
前端·vue.js·node.js
廾匸64041 分钟前
语义化标签
前端·javascript·html
汪汪队立大功1231 小时前
selenium中执行javascript,是否等价于在浏览器console位置执行
javascript·selenium·测试工具
烛阴1 小时前
隐式vs显式:解密C#类型转换的底层逻辑
前端·c#
Fantasydg1 小时前
AJAX JSON学习
前端·学习·ajax
瓢儿菜20182 小时前
Web开发:什么是 HTTP 状态码?
前端·网络协议·http
1024小神2 小时前
swiftui使用WKWebView加载自签的https服务,允许不安全访问
前端
anyup2 小时前
支持鸿蒙!开源三个月,uView Pro 开源库近期更新全面大盘点,及未来计划
前端·vue.js·uni-app