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

写在前面

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

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

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JacksonChen_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值