一起围观由React Hooks防抖引发的面试翻车现场

栏目: IT技术 · 发布时间: 4年前

内容简介:防抖是前端业务常用的工具,也是前端面试的高频问题。平时面试候选人,手写防抖人人都会,但是稍做修改就有小伙伴进坑送命。本文介绍了如何在react hooks中实现防抖。背景—

防抖是前端业务常用的工具,也是前端面试的高频问题。平时面试候选人,手写防抖人人都会,但是稍做修改就有小伙伴进坑送命。本文介绍了如何在react hooks中实现防抖。

背景

防抖(debounce)是前端经常用到的 工具 函数,也是我在面试中必问的一个问题。团队内部推广React Hooks以后,我在面试中也加入了相关的题目。如何实现 useDebounce。 这个看起来很基础的问题,实际操作起来却让很多小伙伴漏出马脚。

面试的设计往往是这样的:

  1. 什么是防抖、节流,分别解释一下?

  2. 在白纸上手写一个防抖or节流函数,自己任选(限时4分钟)

  3. react hooks有了解吗?上机实现一个useDebounce、useThrottle,自己任选

  4. typescript有了解吗?用ts再来写一遍

  5. 聊一聊用到防抖、节流的业务场景

围绕一个主题不断切换考察点,这样一轮下来,轻松又流畅,同时可以试探出很多信息。

实际情况是,很多候选人在第3题就卡住了,不得不说很可惜。

场景还原

写一个防抖函数

一个经典的防抖函数可能是这样的:

function debounce(fn, ms) {

let timer;

return function(...args) {

if (timer) {

clearTimeout(timer)

}

timer = setTimeout(() => {

fn(...args)

timer = null;

}, ms);

}

}

改成react hooks

先提供测试用例:

export default function() {

const [counter, setCounter] = useState(0);


const handleClick = useDebounce(function() {

setCounter(counter + 1)

}, 1000)


return <div style={{ padding: 30 }}>

<Button

onClick={handleClick}

>click</Button>

<div>{counter}</div>

</div>

}

很多小 伙伴 会想当然的就改成这样:

function useDebounce(fn, time) {

return debounce(fn, time);

}

简单、优雅,还复用了刚才的代码,测试一下,看起来并没有什么问题:

一起围观由React Hooks防抖引发的面试翻车现场

但是这个代码如果放上生产环境,你会被用户锤死。

真的吗?

换个用例来试一下:

export default function() {

const [counter1, setCounter1] = useState(0);

const [counter2, setCounter2] = useState(0);


const handleClick = useDebounce(function() {

console.count('click1')

setCounter1(counter1 + 1)

}, 500)


useEffect(function() {

const t = setInterval(() => {

setCounter2(x => x + 1)

}, 500);

return clearInterval.bind(undefined, t)

}, [])



return <div style={{ padding: 30 }}>

<Button

onClick={function() {

handleClick()

}}

>click</Button>

<div>{counter1}</div>

<div>{counter2}</div>

</div>

}

一起围观由React Hooks防抖引发的面试翻车现场

当引入一个自动累加counter2就开始出问题了。这时很多候选人就开始懵了,有的候选人会尝试分析原因。只有深刻理解react hooks在重渲染时的工作原理才能快速定位到问题(事实上出错不要紧,能够快速定位问题的小伙伴才是我们苦苦寻找的)。

有的候选人开启 胡乱 调试大法,慌忙修改setCounter1:

const handleClick = useDebounce(function() {

console.count('click1')

setCounter1(x => x + 1)

}, 500)

当然结果依然错误,而且暴漏了自己对react hooks特性不够熟悉的问题……

有的候选人猜到是重染缓存的问题,于是写成这样:

function useDebounce(fn, delay) {

return useCallback(debounce(fn, delay), [])

}

在配合 setCounter1(x => x + 1) 修改的情况下,可以得到看似正确的结果。但并没有正确解决问题(再说你也不能通过“ 改用例 ”的方式来修bug呀:joy:)。依然是错误的。有兴趣的读者可以复现一下这个现象,思考一下为什么, 欢迎留言讨论

问题出在哪里?

我们在useDebounce里面加个log

function useDebounce(fn, time) {

console.log('usedebounce')

return debounce(fn, time);

}

一起围观由React Hooks防抖引发的面试翻车现场

控制台开始疯狂的输出log。看到这里,很多读者就明白了。如果是前面表现稍好的候选人,可以提示到这一步。

每次组件重新渲染,都会执行一遍所有的hooks,这样debounce高阶函数里面的timer就不能起到缓存的作用(每次重渲染都被置空)。timer不可靠,debounce的核心就被破坏了。

如何调整?

修复这个问题可以有很多办法。比如利用React组件的缓存机制:

function useDebounce(fn, delay) {

const { current } = useRef({});

function f(...args) {

if (current.timer) {

clearTimeout(current.timer);

}

current.timer = setTimeout(fn.bind(undefined, ...args), delay);

}

return f;

}

就可以实现一个可靠的useDebounce。

同理我们直接给出useThrottle的代码:

export function useThrottle(fn, delay) {

const { current } = useRef({});

function f(...args) {

if (!current.timer) {

current.timer = setTimeout(() => {

delete current.timer;

}, delay);

fn(...args);

}

}

return f;

}

最后

使用react hooks可以帮助我们把一些常用的状态逻辑沉淀下来。同时,react hooks引入生产项目的初期要格外留意 写法和原理的差异 所带来的隐患。不然就像上面的候选人一样大意失荆州……

分析一下这道题 易错原因:

  • 马虎大意。debounce很简单,react hooks也不难,万万没想到结合起来就有坑

  • 心态崩坏。面试场景下,遇到没有见过的问题,无法冷静分析。

  • 对react hooks理解不够深刻,踩坑不多

  • 对debounce也不够熟悉,有背代码的嫌疑

由于太多人挂在这个问题上,我决定不再用作面试题,并把它分享出来,希望可以帮到大家。 关于防抖还有些坑呢? 欢迎留言讨论


以上所述就是小编给大家介绍的《一起围观由React Hooks防抖引发的面试翻车现场》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Linux Command Line

The Linux Command Line

William E. Shotts Jr. / No Starch Press, Incorporated / 2012-1-17 / USD 39.95

You've experienced the shiny, point-and-click surface of your Linux computer-now dive below and explore its depths with the power of the command line. The Linux Command Line takes you from your very ......一起来看看 《The Linux Command Line》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具