reactjs - 反应useEffect钩子不调用模拟函数
问题描述
我是 React 钩子的新手。我在组件中使用了 useEffect() 钩子,该钩子从我的道具中调用了一个函数 searchForVideos():
useEffect(() => {
props.searchForVideos();
}, [currentPage]);
该函数在我的单元测试中使用 Jest 进行了模拟:
const searchForVideos = jest.fn();
因此,根据我的理解,useEffect() 应该在组件渲染后立即运行。我可以在 useEffect() 回调中放置一个 console.log() 语句,它会打印到控制台。但是,此 expect() 语句失败:
const component = mountComponent();
setImmediate(() => {
expect(searchForVideos).toHaveBeenCalled();
});
这很奇怪,因为我已经确认钩子正在运行,如果它正在运行,它应该调用该函数。但是,那条线总是失败。
有什么我应该知道的让模拟函数与 React 钩子一起工作吗?
更新
作为对评论的回应,我进行了更改以解决问题。不过,我不明白为什么会这样。
const component = mountComponent();
requestAnimationFrame(() => {
expect(searchForVideos).toHaveBeenCalled();
done();
});
所以我只是用 requestAnimationFrame() 替换了 setImmediate(),现在一切正常。我以前从未接触过 requestAnimationFrame() 。我对 setImmediate() 的理解是,它基本上会立即将回调排队在事件队列的后面,因此队列中的任何其他 JavaScript 任务都会在它之前运行。
因此,理想情况下,我正在寻求有关这些功能以及此更改为何起作用的解释。
解决方案
至于为什么要requestAnimationFrame
修复它的次要问题,请参阅下面的文档摘录。它只是进入了特定的时间,useEffect
并且useLayoutEffect
——特别是“useEffect 被推迟到浏览器绘制之后”。requestAnimationFrame
以类似的方式延迟您的测试代码。我希望如果您将代码更改为 use useLayoutEffect
,您的测试的原始版本将起作用(但useEffect
对于您的情况来说是合适的钩子)。
来自https://reactjs.org/docs/hooks-reference.html#timing-of-effects:
与 componentDidMount 和 componentDidUpdate 不同,传递给 useEffect 的函数在布局和绘制之后在延迟事件期间触发。这使它适用于许多常见的副作用,例如设置订阅和事件处理程序,因为大多数类型的工作不应该阻止浏览器更新屏幕。
但是,并非所有影响都可以推迟。例如,对用户可见的 DOM 突变必须在下一次绘制之前同步触发,以便用户不会感知到视觉上的不一致。(区别在概念上类似于被动和主动事件侦听器。)对于这些类型的效果,React 提供了一个额外的 Hook,称为 useLayoutEffect。它与 useEffect 具有相同的签名,只是在触发时有所不同。
尽管 useEffect 被推迟到浏览器绘制之后,但它保证在任何新的渲染之前触发。在开始新的更新之前,React 总是会刷新先前渲染的效果。
来自https://reactjs.org/docs/hooks-reference.html#uselayouteffect:
签名与 useEffect 相同,但它在所有 DOM 突变后同步触发。使用它从 DOM 中读取布局并同步重新渲染。在 useLayoutEffect 中安排的更新将在浏览器有机会绘制之前同步刷新。
尽可能首选标准 useEffect 以避免阻塞视觉更新。
推荐阅读
- c++ - C++(Windows):将虚拟键代码字符串表示(“VK_F6”)转换为十六进制(0x75)
- c# - C# 将 IHtmlContent 转换为字符串
- python - 在python中以一对一的方式将元素从1个列表附加到另一个列表的嵌套元素
- python - 如何在一行中拆分单词以在 DataFrame 中创建新行?
- django - 表单中的自定义错误
- javascript - 当我单击菜单按钮(onlick)时,它会打开然后立即关闭
- powershell - 如何获取所有报告的数据源用户名?
- python - 如何制作 Discord.py ping cmd
- python - 为什么我的函数不能根据用户输入正确执行?
- r - 更新 R 弹性包导致发送失败:Broken pipe