使用React Testing Library测试时ref.current未赋值的原因
React测试中useRef.current始终为null的原因及解决办法
将以下测试代码中,r.current始终为null,无法被设置为HtmlDivElement,请问原因是什么?我使用的是Jest 27版本的React Testing Library,尝试升级到该库的最新版本后,问题仍未解决。
测试代码:
test('test-1', async () => { const Comp = () => { const r = React.useRef(null); React.useEffect(() => { if (r.current) { console.log(r.current); } }); return <div ref={r}> Hello </div>; }; render(<Comp />); });
核心原因
问题出在测试执行时机与React副作用的异步特性不匹配:
- React的
useEffect回调是异步执行的,会在组件挂载完成后加入任务队列,不会同步阻塞代码执行。 - 你的测试代码调用
render后就直接结束了,此时Jest的测试进程已经终止,useEffect的回调还没来得及执行,自然看不到r.current被赋值后的输出。
解决办法
1. 用waitFor等待副作用执行完成
React Testing Library的waitFor可以等待异步操作完成,确保useEffect的回调执行后再结束测试:
import { render, waitFor } from '@testing-library/react'; import React from 'react'; test('test-1', async () => { let refCurrent = null; const Comp = () => { const r = React.useRef(null); React.useEffect(() => { refCurrent = r.current; if (refCurrent) { console.log(refCurrent); } }); return <div ref={r}> Hello </div>; }; render(<Comp />); // 等待useEffect执行,确保ref被赋值 await waitFor(() => { expect(refCurrent).not.toBeNull(); }); });
2. 遵循RTL测试最佳实践:直接查询DOM元素
如果你的测试目的是验证元素是否渲染,完全不需要依赖useRef,用RTL的查询方法更直接,也符合“测试用户可见行为”的原则:
import { render, screen } from '@testing-library/react'; test('test-1', () => { render(<div> Hello </div>); // 直接查询元素并断言 expect(screen.getByText(' Hello ')).toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者Vimil Saju
相关产品推荐
相关产品推荐

