fix(profile): preserve label account type across page refreshes - #14548
Merged
Conversation
Two bugs caused profile_type to revert to null after switching to label:
1. useUpdateProfile had no onSuccess handler, so the server-confirmed
data returned by mutationFn was discarded entirely. The optimistic
update was left in cache but nothing re-confirmed it after the write
landed.
Fix: add onSuccess that re-applies the mutation variables (not the
raw server response) to the query cache with forceReplace: true.
Using variables rather than the server response guards against
discovery-node propagation lag — the getUser call may hit a node
that has not yet indexed the confirmed block.
2. onError rolled back with { ...context.previousMetadata, ...metadata }
instead of context.previousMetadata alone, effectively applying the
failed mutation on top of the pre-mutation state instead of
restoring it.
Fix: roll back with context.previousMetadata only.
3. setLocalStorageAccountAndUser (called inside fetchAccountAsync on
every page load) wrote the server-fetched accountUser directly to
localStorage, overwriting any recent optimistic updates such as
profile_type. On the next reload, fetchLocalAccountAsync would read
this stale localStorage value and prime the cache with profile_type:
null, reverting the user to artist.
Fix: prefer the React Query cache over the server response when
writing to localStorage. The cache already holds the correct
post-mutation state; the server response may lag due to node
propagation. If the cache is empty (first load), fall back to the
server value as before.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Switching from artist to label account appeared to work, but reverted to artist within ~10 seconds of a page refresh. Reproduced on @FutureVibes and @theboathouse.
Root Cause
Three bugs conspired to cause the revert:
Bug 1 —
useUpdateProfile: noonSuccesshandlermutationFncallssdk.users.updateUser()(entity manager, waits for block confirmation), then fetches fresh user data viasdk.users.getUser()and returns it. But there was noonSuccesshandler, so the server-confirmed data was silently discarded. The optimistic update fromonMutatestayed in the React Query cache, but nothing re-confirmed it after the write landed on-chain.Bug 2 —
useUpdateProfile: brokenonErrorrollbackonErrorrolled back with{ ...context.previousMetadata, ...metadata }instead ofcontext.previousMetadataalone — applying the failed mutation on top of the pre-mutation state, the opposite of a rollback.Bug 3 —
setLocalStorageAccountAndUser: overwrites recent mutationsfetchAccountAsyncruns on every page load and callssetLocalStorageAccountAndUser, which writes the server-fetchedaccountUserdirectly tolocalStorage. This overwrites any recent optimistic updates (e.g.profile_type: label) that haven't yet propagated to all discovery nodes. On the next reload,fetchLocalAccountAsyncreads this stalelocalStoragevalue and primes the cache withprofile_type: null, reverting the user back to artist.Fix
packages/common/src/api/tan-query/users/useUpdateProfile.tsonSuccessthat re-applies the mutation variables to the query cache (forceReplace: true). Uses the mutation variables rather than the raw server response to guard against discovery-node propagation lag — thegetUsercall may hit a node that has not yet indexed the confirmed block.onErrorto roll back withcontext.previousMetadataonly (not spread with currentmetadata).packages/common/src/store/account/sagas.tssetLocalStorageAccountAndUsernow prefers the React Query cached user over the server-fetched response when writing tolocalStorage. The cache already holds the correct post-mutation state; the server may lag due to node propagation. Falls back to the server value if the cache is empty (first load, no prior mutations).Testing
Manually verify with a label-eligible account: