-
-
Notifications
You must be signed in to change notification settings - Fork 112
feat: add ref forwarding to internal img element. Closes #372 #379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 6 commits
b88ff56
0b6f315
338cb86
f8720c3
14a74e3
26a8205
b04e15e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| import { act, fireEvent, render } from '@testing-library/react'; | ||
| import React from 'react'; | ||
| import Image, { ImageRef } from '../src'; | ||
|
|
||
| describe('Image ref forwarding', () => { | ||
| // 测试对象类型的 ref | ||
| it('should provide access to internal img element via nativeElement', () => { | ||
| const ref = React.createRef<ImageRef>(); | ||
| const { container } = render( | ||
| <Image | ||
| ref={ref} | ||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | ||
| alt="test image" | ||
| />, | ||
| ); | ||
|
|
||
| // 确保 ref.current.nativeElement 指向正确的 img 元素 | ||
| expect(ref.current).not.toBeNull(); | ||
| expect(ref.current?.nativeElement).not.toBeNull(); | ||
| expect(ref.current?.nativeElement).toBe(container.querySelector('.rc-image-img')); | ||
|
||
| expect(ref.current?.nativeElement?.tagName).toBe('IMG'); | ||
| expect(ref.current?.nativeElement?.alt).toBe('test image'); | ||
| }); | ||
|
|
||
| // 测试回调类型的 ref | ||
| it('should work with callback ref', () => { | ||
| let imgRef: ImageRef | null = null; | ||
| const callbackRef = (el: ImageRef | null) => { | ||
| imgRef = el; | ||
| }; | ||
|
|
||
| const { container } = render( | ||
| <Image | ||
| ref={callbackRef} | ||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | ||
| />, | ||
| ); | ||
|
|
||
| // 确保回调 ref 被调用,且 nativeElement 指向正确的 img 元素 | ||
| expect(imgRef).not.toBeNull(); | ||
| expect(imgRef?.nativeElement).not.toBeNull(); | ||
|
||
| expect(imgRef?.nativeElement).toBe(container.querySelector('.rc-image-img')); | ||
| }); | ||
|
|
||
| // 测试通过 nativeElement 访问 img 元素的属性和方法 | ||
| it('should allow access to img element properties and methods via nativeElement', () => { | ||
| const ref = React.createRef<ImageRef>(); | ||
| render( | ||
| <Image | ||
| ref={ref} | ||
| width={200} | ||
| height={100} | ||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | ||
| />, | ||
| ); | ||
|
|
||
| // 确保可以通过 ref.nativeElement 访问 img 元素的属性 | ||
| expect(ref.current?.nativeElement?.width).toBe(200); | ||
| expect(ref.current?.nativeElement?.height).toBe(100); | ||
|
|
||
| // 可以测试调用 img 元素的方法 | ||
| // 注意:某些方法可能在 jsdom 环境中不可用,根据实际情况调整 | ||
| }); | ||
|
|
||
| // 测试 ref.nativeElement 在组件重新渲染时保持稳定 | ||
| it('should maintain stable nativeElement reference across re-renders', () => { | ||
| const ref = React.createRef<ImageRef>(); | ||
| const { rerender } = render( | ||
| <Image | ||
| ref={ref} | ||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | ||
| />, | ||
| ); | ||
|
|
||
| const initialImgElement = ref.current?.nativeElement; | ||
| expect(initialImgElement).not.toBeNull(); | ||
|
|
||
| // 重新渲染组件,但保持 ref 不变 | ||
| rerender( | ||
| <Image | ||
| ref={ref} | ||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | ||
| alt="updated alt" | ||
| />, | ||
| ); | ||
|
|
||
| // 确保 ref.nativeElement 引用的还是同一个 img 元素 | ||
| expect(ref.current?.nativeElement).toBe(initialImgElement); | ||
| expect(ref.current?.nativeElement?.alt).toBe('updated alt'); | ||
| }); | ||
|
|
||
| // 测试 ref 不能直接访问 img 元素属性 | ||
|
||
| it('should not allow direct access to img element properties', () => { | ||
| const ref = React.createRef<ImageRef>(); | ||
| render( | ||
| <Image | ||
| ref={ref} | ||
| src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" | ||
| />, | ||
| ); | ||
|
|
||
| // 确保 ref.current 不是 HTMLImageElement | ||
| expect(ref.current).not.toBeNull(); | ||
| // @ts-ignore - 故意测试运行时行为 | ||
| expect(ref.current.tagName).toBeUndefined(); | ||
| // @ts-ignore - 故意测试运行时行为 | ||
| expect(ref.current.src).toBeUndefined(); | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
集成内部和外部引用的处理函数
handleRef函数巧妙地处理了内部引用的存储和对getImgRef的调用,确保了与现有功能的兼容性。但是,这里有一个潜在的问题:当 img 元素为 null 时直接返回了,但没有更新imageElementRef.current。应该考虑在这种情况下将imageElementRef.current也设置为 null。const handleRef = (img: HTMLImageElement | null) => { if (!img) { + imageElementRef.current = null; return; } // 保存到内部引用 imageElementRef.current = img; getImgRef(img); };📝 Committable suggestion