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

相关推荐
庸俗今天不摸鱼28 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX1873029 分钟前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下35 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox1 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞1 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行1 小时前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_593758101 小时前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周1 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
Jasmin Tin Wei2 小时前
蓝桥杯 web 学海无涯(axios、ecahrts)版本二
前端·蓝桥杯