Skip to content

Commit 04cf0e3

Browse files
Fix profile tab routing (#13835)
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> Fixes profile tab routing to correctly display the specified tab for profile sub-routes like `/handle/albums`. This PR resolves a race condition in the `useProfilePage` hook where the `activeTab` was incorrectly reset to `null` and then overridden by the default tab logic before the URL tab could be applied. The fix ensures the URL tab parameter is prioritized during initialization and preserved when the profile handle changes. --- [Slack Thread](https://audius-internal.slack.com/archives/C02JBA52NKZ/p1772826591082269?thread_ts=1772826591.082269&cid=C02JBA52NKZ) <p><a href="https://cursor.com/agents/bc-f2f59d69-e616-50d8-b44a-90ec5dc0f52f"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-f2f59d69-e616-50d8-b44a-90ec5dc0f52f"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</p> <!-- CURSOR_AGENT_PR_BODY_END --> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Dylan Jeffers <dylanjeffers@users.noreply.github.com>
1 parent e44d789 commit 04cf0e3

2 files changed

Lines changed: 36 additions & 5 deletions

File tree

packages/web/src/pages/profile-page/ProfilePage.test.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ const ProfilePageWithRef = () => {
6262
)
6363
}
6464

65-
export function renderProfilePage(user: any, options?: RenderOptions) {
65+
export function renderProfilePage(
66+
user: any,
67+
options?: RenderOptions & { initialRoute?: string }
68+
) {
69+
const { initialRoute, ...renderOptions } = options ?? {}
6670
mswServer.use(
6771
mockUserByHandle(user),
6872
mockRelatedUsers(user),
@@ -75,8 +79,9 @@ export function renderProfilePage(user: any, options?: RenderOptions) {
7579
<Routes>
7680
<Route path='/' element={<Navigate to='/test-user' replace />} />
7781
<Route path='/:handle' element={<ProfilePageWithRef />} />
82+
<Route path='/:handle/:tab' element={<ProfilePageWithRef />} />
7883
</Routes>,
79-
options
84+
renderOptions
8085
)
8186
}
8287

@@ -249,4 +254,26 @@ describe('ProfilePage', () => {
249254
expect(await screen.findByText('$MOCK')).toBeInTheDocument()
250255
expect(screen.queryByText('Tip $AUDIO')).not.toBeInTheDocument()
251256
})
257+
258+
it('should navigate to the correct tab when using sub-routes', async () => {
259+
renderProfilePage(artistUser, {
260+
initialRoute: `/${artistUser.handle}/albums`
261+
})
262+
263+
// Wait for the profile to load
264+
expect(
265+
await screen.findByRole('heading', {
266+
name: new RegExp(`^${artistUser.name}\\s*$`)
267+
})
268+
).toBeInTheDocument()
269+
270+
// Verify that the Albums tab is active (not the first tab)
271+
const navBanner = await screen.findByTestId('nav-banner')
272+
const albumsTab = await within(navBanner).findByText('Albums')
273+
expect(albumsTab).toBeInTheDocument()
274+
275+
// The active tab should have specific styling - check parent for active class
276+
const albumsTabParent = albumsTab.closest('[role="tab"]')
277+
expect(albumsTabParent).toBeInTheDocument()
278+
})
252279
})

packages/web/src/pages/profile-page/useProfilePage.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ export const useProfilePage = (
120120
const currentTrack = useCurrentTrack()
121121

122122
// Local state
123-
const [activeTab, setActiveTab] = useState<ProfilePageTabs | null>(null)
123+
const [activeTab, setActiveTab] = useState<ProfilePageTabs | null>(() => {
124+
// Initialize with tab from URL if present
125+
return params?.tab ? getTabForRoute(params.tab) : null
126+
})
124127
const [editMode, setEditMode] = useState(false)
125128
const [shouldMaskContent, setShouldMaskContent] = useState(false)
126129
const [tracksLineupOrder, setTracksLineupOrder] = useState<TracksSortMode>(
@@ -230,7 +233,8 @@ export const useProfilePage = (
230233

231234
// Reset state when profile changes
232235
useEffect(() => {
233-
setActiveTab(null)
236+
// Preserve tab from URL if present, otherwise reset to null
237+
setActiveTab(params?.tab ? getTabForRoute(params.tab) : null)
234238
setEditMode(false)
235239
setUpdatedName(null)
236240
setUpdatedCoverPhoto(null)
@@ -243,7 +247,7 @@ export const useProfilePage = (
243247
setUpdatedWebsite(null)
244248
setUpdatedArtistCoinBadge(null)
245249
setAreArtistRecommendationsVisible(false)
246-
}, [profile?.handle])
250+
}, [profile?.handle, params?.tab])
247251

248252
// Check if owner changed from visitor to owner
249253
useEffect(() => {

0 commit comments

Comments
 (0)