Skip to content

fix: support fetchPriority compatibility for React 18 and 19#503

Closed
sahsahvedov wants to merge 6 commits intoreact-component:masterfrom
sahsahvedov:fix/fetchpriority-compat
Closed

fix: support fetchPriority compatibility for React 18 and 19#503
sahsahvedov wants to merge 6 commits intoreact-component:masterfrom
sahsahvedov:fix/fetchpriority-compat

Conversation

@sahsahvedov
Copy link

@sahsahvedov sahsahvedov commented Mar 22, 2026

Summary by CodeRabbit

发布说明

  • 新功能

    • 添加了图片加载优先级功能,支持通过属性控制图片资源的加载优先级(高、低、自动)。
  • 改进

    • 增强了对不同React版本的兼容性支持。
  • 测试

    • 新增单元测试验证加载优先级功能在各版本中的表现。

@vercel
Copy link

vercel bot commented Mar 22, 2026

@test12376 is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Mar 22, 2026

Warning

Rate limit exceeded

@sahsahvedov has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 44 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2e01a9f3-866d-41d1-9278-7673d9ed6e84

📥 Commits

Reviewing files that changed from the base of the PR and between 088f6f1 and 5f3a754.

📒 Files selected for processing (4)
  • src/Image.tsx
  • src/PreviewGroup.tsx
  • src/interface.ts
  • tests/previewGroup.test.tsx

Walkthrough

此PR添加了对HTML fetchPriority属性的支持,包括React版本兼容性处理。新增工具函数根据React版本(18及以下使用小写fetchpriority,19+使用驼峰fetchPriority)返回相应的属性对象,并扩展了Image组件的prop支持和接口定义。

Changes

分组 / 文件 变更摘要
Fetch Priority 核心实现
src/interface.ts, src/util.ts
新增 FetchPriority 类型定义;添加了 getFetchPriorityProps() 工具函数,根据React版本动态返回小写或驼峰格式的fetchPriority属性;扩展 ImageElementProps 接口以包含新属性。
Image 组件增强
src/Image.tsx
扩展了<img>元素支持的属性(crossOrigindecodingdraggablefetchPriorityloadingreferrerPolicysizessrcSetuseMap);重构了 imgCommonProps 构造逻辑以集成 getFetchPriorityProps();更新了 useMemo 依赖列表。
Preview 组件调整
src/Preview/index.tsx
useRef 初始值改为显式 null,对齐ref的运行时类型。
测试覆盖
tests/fetchPriority.test.tsx, tests/preview.test.tsx
新增测试套件验证 getFetchPriorityProps() 在React 18和19下的行为差异;更新preview测试以验证fetchPriority属性的正确传递。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • zombieJ
  • thinkasany

Poem

🐰✨ Fetch priority now flows with grace,
React versions handled in their place,
Lowercase then camel, the logic gleams,
Tests ensure all works as it seems!
Props expand, compatibility shines,
A fluffy change across the lines.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确总结了主要变更:为React 18和19添加fetchPriority兼容性支持,与代码库中的具体实现完全一致。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces support for the fetchPriority attribute, allowing developers to hint at the priority of image fetching to the browser. It specifically addresses compatibility across React 18 and React 19 by dynamically adjusting the attribute's casing (fetchpriority vs. fetchPriority) based on the detected React version, ensuring correct behavior in different environments.

Highlights

  • Feature Addition: Introduced support for the fetchPriority attribute on image elements.
  • React Version Compatibility: Implemented logic to dynamically apply fetchPriority as fetchpriority (lowercase) for React 18 and fetchPriority (camelCase) for React 19, addressing API differences.
  • New Utility Function: Added getFetchPriorityProps in src/util.ts to encapsulate the React version-specific fetchPriority handling.
  • Enhanced Image Component: Updated the Image component to accept and correctly pass through the fetchPriority prop along with other standard image attributes.
  • Comprehensive Testing: Included new unit tests for the getFetchPriorityProps utility and updated existing integration tests to verify fetchPriority behavior.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for the fetchPriority prop, ensuring compatibility between React 18 and React 19 by dynamically using either fetchpriority or fetchPriority based on the React version. The changes include updating type definitions, adding a utility function to determine the correct prop, and adding relevant tests. My main feedback is to refactor a useMemo hook for better maintainability.

Comment on lines 173 to 200
() => {
const obj: ImageElementProps = {};
COMMON_PROPS.forEach((prop: any) => {
if (props[prop] !== undefined) {
obj[prop] = props[prop];
if (prop === 'fetchPriority') {
Object.assign(obj, getFetchPriorityProps(fetchPriority));
} else if (prop === 'crossOrigin' && crossOrigin !== undefined) {
obj.crossOrigin = crossOrigin;
} else if (prop === 'decoding' && decoding !== undefined) {
obj.decoding = decoding;
} else if (prop === 'draggable' && draggable !== undefined) {
obj.draggable = draggable;
} else if (prop === 'loading' && loading !== undefined) {
obj.loading = loading;
} else if (prop === 'referrerPolicy' && referrerPolicy !== undefined) {
obj.referrerPolicy = referrerPolicy;
} else if (prop === 'sizes' && sizes !== undefined) {
obj.sizes = sizes;
} else if (prop === 'srcSet' && srcSet !== undefined) {
obj.srcSet = srcSet;
} else if (prop === 'useMap' && useMap !== undefined) {
obj.useMap = useMap;
} else if (prop === 'alt' && alt !== undefined) {
obj.alt = alt;
}
});

return obj;
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This useMemo callback can be simplified to improve readability and maintainability. The current implementation uses a long if-else if chain, which is verbose and harder to maintain when adding or removing props.

Consider refactoring this to build the props object more dynamically by separating the generic props from the special case for fetchPriority.

    () => {
      const propsToPass = {
        alt,
        crossOrigin,
        decoding,
        draggable,
        loading,
        referrerPolicy,
        sizes,
        srcSet,
        useMap,
      };

      const obj: Partial<ImageElementProps> = {};
      for (const key in propsToPass) {
        if (Object.prototype.hasOwnProperty.call(propsToPass, key) && propsToPass[key] !== undefined) {
          obj[key] = propsToPass[key];
        }
      }

      Object.assign(obj, getFetchPriorityProps(fetchPriority));

      return obj;
    },

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Image.tsx (1)

172-202: 建议简化 imgCommonProps 的构建逻辑。

当前实现遍历 COMMON_PROPS 数组,但每个属性都使用硬编码的字符串比较进行处理。这使得循环变得冗余且难以维护。

♻️ 建议的简化方案
  const imgCommonProps = useMemo(
    () => {
-     const obj: ImageElementProps = {};
-     COMMON_PROPS.forEach((prop: any) => {
-       if (prop === 'fetchPriority') {
-         Object.assign(obj, getFetchPriorityProps(fetchPriority));
-       } else if (prop === 'crossOrigin' && crossOrigin !== undefined) {
-         obj.crossOrigin = crossOrigin;
-       } else if (prop === 'decoding' && decoding !== undefined) {
-         obj.decoding = decoding;
-       } else if (prop === 'draggable' && draggable !== undefined) {
-         obj.draggable = draggable;
-       } else if (prop === 'loading' && loading !== undefined) {
-         obj.loading = loading;
-       } else if (prop === 'referrerPolicy' && referrerPolicy !== undefined) {
-         obj.referrerPolicy = referrerPolicy;
-       } else if (prop === 'sizes' && sizes !== undefined) {
-         obj.sizes = sizes;
-       } else if (prop === 'srcSet' && srcSet !== undefined) {
-         obj.srcSet = srcSet;
-       } else if (prop === 'useMap' && useMap !== undefined) {
-         obj.useMap = useMap;
-       } else if (prop === 'alt' && alt !== undefined) {
-         obj.alt = alt;
-       }
-     });
-
-     return obj;
+     return {
+       ...(alt !== undefined && { alt }),
+       ...(crossOrigin !== undefined && { crossOrigin }),
+       ...(decoding !== undefined && { decoding }),
+       ...(draggable !== undefined && { draggable }),
+       ...(loading !== undefined && { loading }),
+       ...(referrerPolicy !== undefined && { referrerPolicy }),
+       ...(sizes !== undefined && { sizes }),
+       ...(srcSet !== undefined && { srcSet }),
+       ...(useMap !== undefined && { useMap }),
+       ...getFetchPriorityProps(fetchPriority),
+     };
    },
    [alt, crossOrigin, decoding, draggable, fetchPriority, loading, referrerPolicy, sizes, srcSet, useMap],
  );

这种方式更简洁,且不依赖于 COMMON_PROPS 数组的遍历。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Image.tsx` around lines 172 - 202, The imgCommonProps builder is overly
verbose by iterating COMMON_PROPS and hardcoding property checks; simplify by
directly constructing the ImageElementProps object using the known prop
variables and only assigning those that are defined (handle fetchPriority via
getFetchPriorityProps(fetchPriority)), i.e., create obj with conditional
assignments for alt, crossOrigin, decoding, draggable, loading, referrerPolicy,
sizes, srcSet, useMap and merge getFetchPriorityProps when fetchPriority is
present, replacing the COMMON_PROPS loop in the imgCommonProps useMemo.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Preview/index.tsx`:
- Line 197: The imgRef is created as useRef<HTMLImageElement>(null) which yields
RefObject<HTMLImageElement> but useImageTransform, useMouseEvent, useTouchEvent
and the PreviewImageProps interface currently expect
MutableRefObject<HTMLImageElement>, causing a type mismatch; update the
parameter and prop types in useImageTransform, useMouseEvent, useTouchEvent and
PreviewImageProps to accept RefObject<HTMLImageElement> (or HTMLImageElement |
null where appropriate) so callers can pass imgRef directly, and ensure any
internal reads guard for null (e.g., check imgRef.current before accessing
offsetWidth/offsetHeight/getBoundingClientRect); alternatively, if you prefer
minimal change, add a type assertion where imgRef is passed (e.g., imgRef as
unknown as MutableRefObject<HTMLImageElement>), but the preferred fix is
changing the hooks and interface signatures to RefObject<HTMLImageElement>.

---

Nitpick comments:
In `@src/Image.tsx`:
- Around line 172-202: The imgCommonProps builder is overly verbose by iterating
COMMON_PROPS and hardcoding property checks; simplify by directly constructing
the ImageElementProps object using the known prop variables and only assigning
those that are defined (handle fetchPriority via
getFetchPriorityProps(fetchPriority)), i.e., create obj with conditional
assignments for alt, crossOrigin, decoding, draggable, loading, referrerPolicy,
sizes, srcSet, useMap and merge getFetchPriorityProps when fetchPriority is
present, replacing the COMMON_PROPS loop in the imgCommonProps useMemo.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 103f7020-0ebc-429c-b881-95274a7e344d

📥 Commits

Reviewing files that changed from the base of the PR and between 718a756 and 981714d.

📒 Files selected for processing (7)
  • src/Image.tsx
  • src/Preview/index.tsx
  • src/common.ts
  • src/interface.ts
  • src/util.ts
  • tests/fetchPriority.test.tsx
  • tests/preview.test.tsx

@sahsahvedov
Copy link
Author

@aojunhao123 Can you please merge this pr, need to ant-design/ant-design#57335

@aojunhao123
Copy link
Contributor

aojunhao123 commented Mar 22, 2026

Thanks for the PR! I've noticed this issue too and landed a simpler fix in #504 — just adding fetchPriority to the existing COMMON_PROPS whitelist. But appreciate you catching this — feel free to keep contributing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants