mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +00:00
fix(ui): stable React list keys on Now Playing cards (#703)
* fix(ui): use stable list keys on Now Playing dashboard cards Subsonic payloads can repeat the same id in similar artists, album track rows, and top songs. Keys now combine id with list index so React reconciliation stays stable and duplicate-key warnings stop. * docs: changelog and credits for Now Playing list keys (PR #703) Document the dashboard list key fix in CHANGELOG and Settings contributors.
This commit is contained in:
@@ -289,6 +289,12 @@ Foundational work: faster reviews, narrower diffs, and a safety net under the pa
|
||||
|
||||
* **Add Station** / **Edit** now mount **`RadioEditModal`** with **`createPortal(..., document.body)`** (same layering approach as **Search Directory**). Previously the overlay lived under nested **`.content-body`** with **`contain: paint`**, so on an **empty** station list the fixed overlay was **painted inside a short box** and looked cropped; after the first station the layout was tall enough that the bug was easy to miss.
|
||||
|
||||
### Now Playing — stable list keys on dashboard cards (duplicate React `key` warnings)
|
||||
|
||||
**By [@cucadmuh](https://github.com/cucadmuh), PR [#703](https://github.com/Psychotoxical/psysonic/pull/703)**
|
||||
|
||||
* **Similar artists**, the **track list inside the in-player album card**, and **Top songs** can all include **more than one row with the same Subsonic `id`** (server payloads are not always strictly deduped). Those lists used **`key={id}`**, which triggered **duplicate `key`** warnings in React devtools and made reconciliation depend on row order. Keys now combine **`id` with the list index** — rendering only; **no queue or playback change**.
|
||||
|
||||
### Search — hide duplicate artist hits with zero albums
|
||||
|
||||
**By [@cucadmuh](https://github.com/cucadmuh), thanks to zunoz for the report on the Psysonic Discord, PR [#697](https://github.com/Psychotoxical/psysonic/pull/697)**
|
||||
|
||||
@@ -69,10 +69,10 @@ const AlbumCard = memo(function AlbumCard({ album, songs, currentTrackId, albumN
|
||||
</span>
|
||||
</div>
|
||||
<div className="np-album-tracklist">
|
||||
{visibleSongs.map(track => {
|
||||
{visibleSongs.map((track, idx) => {
|
||||
const isActive = track.id === currentTrackId;
|
||||
return (
|
||||
<div key={track.id}
|
||||
<div key={`${track.id}-${idx}`}
|
||||
className={`np-album-track${isActive ? ' active' : ''}`}>
|
||||
<span className="np-album-track-num">
|
||||
{isActive
|
||||
|
||||
@@ -81,8 +81,8 @@ const ArtistCard = memo(function ArtistCard({ artistName, artistId, artistInfo,
|
||||
{similar.length > 0 && (
|
||||
<div className="np-dash-similar">
|
||||
<div className="np-dash-chip-row">
|
||||
{similar.slice(0, 12).map(a => (
|
||||
<span key={a.id} className="np-chip"
|
||||
{similar.slice(0, 12).map((a, idx) => (
|
||||
<span key={`${a.id}-${idx}`} className="np-chip"
|
||||
onClick={() => a.id && onNavigate(`/artist/${a.id}`)}
|
||||
data-tooltip={t('nowPlaying.goToArtist')}>
|
||||
{a.name}
|
||||
|
||||
@@ -35,7 +35,7 @@ const TopSongsCard = memo(function TopSongsCard({ artistName, artistId, songs, c
|
||||
{top.map((s, idx) => {
|
||||
const isActive = s.id === currentTrackId;
|
||||
return (
|
||||
<div key={s.id}
|
||||
<div key={`${s.id}-${idx}`}
|
||||
className={`np-dash-top-row${isActive ? ' active' : ''}`}
|
||||
onClick={() => onPlay(s)}
|
||||
data-tooltip={t('contextMenu.playNow')}>
|
||||
|
||||
@@ -110,6 +110,7 @@ const CONTRIBUTOR_ENTRIES = [
|
||||
'OpenSubsonic albumArtists in album header; track artists in player bar, mobile, mini + songToTrack (#552) (PR #696)',
|
||||
'Search: filter search3 artist rows with zero albums (report: zunoz on Psysonic Discord) (PR #697)',
|
||||
'Internet Radio: portal add/edit station modal to document.body — fixes clipped modal on empty library (report: voidboywannabe on Psysonic Discord) (PR #699)',
|
||||
'Now Playing: composite list keys on similar artists, album-card tracklist, and top songs — avoids duplicate React keys when Subsonic repeats ids (PR #703)',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user