Skip to content

Conversation

@theianmay
Copy link
Member

@theianmay theianmay commented Oct 31, 2025

Motivation

This PR addresses issue #3989 where custom rating images were not rendering correctly in the SwipeRating component. While investigating and fixing this issue, several additional bugs were discovered and resolved.

Primary Issue (from #3989):

  • Custom rating images (type="custom" with ratingImage prop) were not displaying - component would show stars instead
  • Rating colors and backgrounds were not applying correctly for custom types

Additional Issues Discovered During Investigation:

  1. Memory Leak in SwipeRating: Animated.Value listener was never cleaned up on unmount. This pattern can cause memory leaks and "Can't perform a React state update on an unmounted component" warnings when navigating away from components using SwipeRating.
  2. Animation Bug in TapRating: Star bounce animation would get stuck at 1.2x scale when tapping stars (discovered during testing in example app)
  3. Test Failures: Inconsistent testIDs and incorrect test expectations causing 7 test failures

Context:
While testing the custom images fix in the example app, I compared the implementation with the original react-native-ratings library and discovered the missing listener cleanup. User interaction testing revealed the animation persistence bug in TapRating.

Fixes #3989

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • Jest Unit Test - All 328 tests passing (6 pre-existing skipped tests in SearchBar)
  • Checked with example app - Verified custom water droplet images render correctly, smooth animations on Android emulator, no memory warnings

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Additional context

Technical Details:

  • Fixed [getPrimaryViewStyle()] and [getSecondaryViewStyle()] to properly handle custom type colors
  • Fixed renderRatings to use ratingImage when type="custom"
  • Used React.useRef to persist Animated.Value across renders (prevents animation interruption)
  • Added proper listener cleanup in useEffect return function (prevents memory leaks)
  • Standardized testIDs to match library and ensured all relevant are enabled
  • Fixed test that incorrectly expected ratingColor to affect tintColor (should use tintColor prop)

…able shadowing in TapRating component

- Renamed position parameter to selectedPosition in starSelectedInPosition function for better clarity
- Updated function references to use the new parameter name consistently
- No behavioral changes, purely internal code  improvement to resolve ESLint warning
- Alphabetically sorted dev dependencies in root package.json for better readability
- Removed unused @rn-vui/ratings package from base/package.json dependencies
- Code now imports from local files after the integration
- Removed hardcoded custom type fallback from TYPES object to prevent conflicts with user-provided images
- Updated renderRatings to use provided ratingImage prop when type is 'custom'
- Added ratingImage dependency to useMemo to ensure proper re-rendering when custom image changes
- Fixed potential undefined source issue when using custom rating type
- Re-enabled previously commented out test case for SwipeRating custom image functionality
- Test verifies that SwipeRating component correctly renders with custom bell.png image
- Ensures custom image source is properly passed to all rating elements
- Added support for custom rating colors when type is 'custom', using ratingColor and ratingBackgroundColor props
- Fixed text color logic to use ratingTextColor prop or fallback to type-based color
- Removed direct tintColor application on rating images for temporary testing
- Consolidated color logic to use consistent textColor variable throughout component
- Added clarifying comment about 'custom' rating type handling in SwipeRating component
- Documented that custom type uses props directly (ratingImage, ratingColor, ratingBackgroundColor) instead of TYPES entry
- Explained conditional logic approach for custom rating type implementation
- Added tintColor prop to SwipeRating component to allow customization of rating image color
- Updated image style to apply the tintColor prop value
- Added tintColor to useCallback dependency array to ensure proper re-rendering when color changes
- Added ratingBackgroundColor prop to customize the inactive icon color in ratings view
- Set default background color to light gray (#c8c7c8) to improve visual contrast
- Maintains existing water-themed rating image and blue active color scheme
- Added useEffect hook to properly manage position listener lifecycle
- Added cleanup function to remove position listener on component unmount
- Wrapped position.addListener in useEffect to ensure proper dependency tracking
- Fixed potential memory leak from dangling animation listener
- Updated test IDs from RNVUI to RNEUI prefix for consistency across components
- Changed test IDs in SwipeRating component and its tests
- Changed test IDs in TapRating component and its tests
- Updated test ID in Star component
- Updated corresponding snapshot tests to reflect new test ID naming
- Wrapped Animated.Value in useRef hook to maintain single animation instance across re-renders
- Changed direct value assignment to use ref.current to ensure proper cleanup
- Prevents creation of new Animated.Value on each render which could cause performance issues and memory leaks
- Updated test ID format from "RNEUI_Star" to "RNEUI__Star" for consistency with design system conventions
- Updated test ID format from "RNEUI_Star-image" to "RNEUI__Star-image" to match new pattern
- Renamed prop from ratingColor to tintColor in SwipeRating test to align with component API
@theianmay theianmay self-assigned this Oct 31, 2025
@theianmay theianmay merged commit 741fa08 into react-native-elements:next Oct 31, 2025
5 checks passed
github-actions bot pushed a commit to theianmay/react-native-elements that referenced this pull request Oct 31, 2025
…atings-lint-custimg-fixes

fix(AirbnbRating): Custom images not rendering, memory leak, and animation bugs
github-actions bot pushed a commit to theianmay/react-native-elements that referenced this pull request Oct 31, 2025
…atings-lint-custimg-fixes

fix(AirbnbRating): Custom images not rendering, memory leak, and animation bugs
@theianmay theianmay deleted the bugfix/ratings-lint-custimg-fixes branch November 5, 2025 05:36
@theianmay theianmay moved this from In Progress 🚧 to Closed or Merged 🏁 in Community Roadmap 🛣 Nov 16, 2025
@github-project-automation github-project-automation bot moved this from In Progress 🚧 to Closed or Merged 🏁 in Community Roadmap 🛣 Nov 16, 2025
@github-project-automation github-project-automation bot moved this to In Progress 🚧 in Community Roadmap 🛣 Nov 16, 2025
@theianmay theianmay added this to the v5.0.0 milestone Nov 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Closed or Merged 🏁

Development

Successfully merging this pull request may close these issues.

SwipeRating: custom rating images

1 participant