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

相关推荐
Java小卷32 分钟前
低代码表单联动配置:从节点驱动到数据驱动
前端·低代码
DianSan_ERP41 分钟前
WMS接入电商平台自动化履约实战:一张订单从平台到出库的接口时序设计
java·前端·网络·数据库·安全·架构·自动化
莪_幻尘42 分钟前
手把手书写你的第一个 AI Agent:当 Skill 有了记忆、角色和主动性
前端·agent
原则猫1 小时前
设计模式
前端
光影少年1 小时前
react navite环境与工程化
前端·react native·react.js
PedroQue992 小时前
v2.6.0 新增全局返回守卫与 iOS 侧滑拦截,补齐跨端路由拦截能力
前端·uni-app
lichenyang4532 小时前
从「房间」到「实时通知」:用 NestJS + Socket.IO 实现团队邀请的完整工程实践
前端·后端
ly76892 小时前
Vue 3 从入门到工程实践:基础语法、组件化、路由、状态管理与项目部署
前端·javascript·vue.js
掘金酱2 小时前
TRAE Work 实战帮征文 | 获奖名单公示
前端·人工智能·后端
陆枫Larry2 小时前
Chromium和Chrome到底是什么关系?
前端