fix: profile avatar cache busting and refresh mechanism
I fixed an issue where updating a profile avatar wasn’t showing the new image immediately after going back to the ProfileView. The old cached image would keep showing until the user saved again or manually refreshed.
Issue(s) Fixes bug: #6794
Problem
When a user updates their avatar and goes back to the ProfileView, the old avatar still appears. This happens because:
- expo-image caches images very aggressively
- The
avatarETagwasn't updating correctly across databases - The
useAvatarETaghook didn’t re-run when the value changed - There was no proper cache-busting or refresh mechanism
What I Did
I added a few coordinated fixes to make sure the avatar updates instantly:
-
useAvatarETag
- Made it always listen for changes (removed the old condition)
- Set the initial value right away
- Fixed the effect dependencies so it re-runs correctly
-
Avatar component
- Added a cache-busting
_cb=${avatarETag}query param to the image URL - Added a
keybased onavatarETagso the image remounts when updated - Used
useMemoto generate the final avatar URL
- Added a cache-busting
-
ProfileView
- Added a refresh key that updates when returning to the view
- Used it to force the avatar container to remount
- Cleared the in-memory image cache on focus
-
connect.ts
- When updating the avatar, I now also sync the logged-in user’s
avatarETagin Redux - This triggers the saga to update the database, so the hook immediately detects changes
- When updating the avatar, I now also sync the logged-in user’s
Summary by CodeRabbit
- Bug Fixes
- More reliable avatar updates: avatar images now remount when their source changes to ensure fresh display.
- Improved avatar synchronization: avatar change events are propagated to remote servers to keep records consistent.
- Performance
- Enhanced image caching using a memory-disk policy for faster load and reduced network use.
- Stability
- More robust avatar observation and cleanup to avoid stale updates after unmount.
✏️ Tip: You can customize this high-level summary in your review settings.
Walkthrough
Image remounting and cache policy were added to Avatar; the ETag observation hook now runs unconditionally and tracks more dependencies; avatarETag updates for the logged-in user are synchronized to the servers database after updateAvatar events.
Changes
| Cohort / File(s) | Summary |
|---|---|
Avatar component rendering app/containers/Avatar/Avatar.tsx |
Image now receives key={${uri}-${avatarETag |
Avatar ETag observation hook app/containers/Avatar/useAvatarETag.ts |
Removed outer guard so observeAvatarETag runs unconditionally; inlined direct-user logic; added local isSubscribed flag for lifecycle safety; consolidated record resolution inline; extended useEffect deps to [username, text, id, rid, type]. |
Server synchronization app/lib/services/connect.ts |
After local avatarETag update, if the updated username matches the logged-in user, update that user's avatarETag in the servers database; includes handling for missing server records. |
Sequence Diagram(s)
sequenceDiagram
actor User
participant Avatar as Avatar Component
participant Hook as useAvatarETag Hook
participant DB as App DB
participant ServerDB as Servers DB
participant Connect as connect service
User->>Avatar: update avatar
Avatar->>Hook: effect re-evaluates (deps: username,text,id,rid,type)
Hook->>DB: observeAvatarETag (unconditional)
DB-->>Hook: record observable
Hook-->>Avatar: avatarETag updated
Avatar->>Avatar: Image remount (new key)
Avatar-->>User: render updated avatar
Note over Connect,ServerDB: sync logged-in user's ETag
DB->>Connect: emit updateAvatar event
Connect->>ServerDB: update avatarETag for logged-in user (if username matches)
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
- Pay attention to lifecycle and subscription correctness in
useAvatarETag.ts(isSubscribed flag, cleanup). - Verify remount implications and performance for
Avatar.tsxwhen forcing Image key changes. - Confirm
connect.tscorrectly locates and updates server records and handles missing-record errors.
Suggested reviewers
- OtavioStasiak
Poem
🐇 I hop through bytes and tags so bright,
Remounting faces into light,
ETags flutter, servers sing,
A little sync, a joyful spring,
Your avatar bounces — what a sight! ✨
Pre-merge checks and finishing touches
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | ⚠️ Warning | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | You can run @coderabbitai generate docstrings to improve docstring coverage. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title accurately describes the main objective of the PR—fixing avatar cache busting and refresh mechanisms to resolve the issue where updated profile avatars didn't appear immediately. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
This change is done by AI and i don't think you have done the testing in iOS and Android.
-
You have added
react-native-skeleton-placeholderbut package.json, package-lock.json, ios/Podfile.lock files are missing from the PR. -
Please explain why we have to clear all images from the memory cache after one user avatar changes
Image.clearMemoryCache().catch(() => {
// Ignore errors if cache clearing fails
});
- Can you provide a recording of this feature as working
It was showing the old avatar due to cache... so i clear cache after avatar change so that it request fresh fetch of avatar from server...
https://github.com/user-attachments/assets/d6be4946-abd8-464f-a8e3-f4e37696a39f
here's the recording
Thanks