fix: Playlist search modal losing state (#974)

fix: Playlist modal retaining state

Replaced usage of crypto.randomUUID() in React keys with a persistent 'id' property on modal objects. This ensures stable keys for modal overlays and modal components, preventing unnecessary re-renders and improving React reconciliation.
This commit is contained in:
Ângelo Tadeucci
2025-12-29 19:21:13 -03:00
committed by GitHub
parent bf1d9408d8
commit 2512165898
2 changed files with 4 additions and 4 deletions
@@ -74,9 +74,9 @@ export function Modal() {
return (
<AnimatePresence>
{currentModal ? <motion.span key={crypto.randomUUID()} onClick={onOverlayClicked} className="fixed size-full bg-black z-[90]" initial={{ opacity: 0 }} animate={{ opacity: currentModal && 0.6 }} exit={{ opacity: 0 }} transition={{ duration: 0.2 }} /> : undefined}
{currentModal ? <motion.span key="modal-overlay" onClick={onOverlayClicked} className="fixed size-full bg-black z-[90]" initial={{ opacity: 0 }} animate={{ opacity: currentModal && 0.6 }} exit={{ opacity: 0 }} transition={{ duration: 0.2 }} /> : undefined}
{modals?.map(modal => (
<motion.div key={crypto.randomUUID()} className="fixed z-[90] top-1/2 left-1/2" initial={{ y: "100vh", x: "-50%" }} animate={{y: "-50%", scale: modal === currentModal ? 1 : 0, opacity: modal === currentModal ? 1 : 0, display: modal === currentModal ? "block" : ["block", "none"]}} exit={{ y: "100vh" }}>
<motion.div key={modal.id} className="fixed z-[90] top-1/2 left-1/2" initial={{ y: "100vh", x: "-50%" }} animate={{y: "-50%", scale: modal === currentModal ? 1 : 0, opacity: modal === currentModal ? 1 : 0, display: modal === currentModal ? "block" : ["block", "none"]}} exit={{ y: "100vh" }}>
{renderModal(modal)}
</motion.div>
))}
+2 -2
View File
@@ -24,7 +24,7 @@ export class ModalService {
const promise = new Promise<ModalResponse<T>>(resolve => {
resolver = resolve as (value: ModalResponse | PromiseLike<ModalResponse>) => void;
});
const modalObj = {modal: modal as ModalComponent, resolver, options};
const modalObj = {id: crypto.randomUUID(), modal: modal as ModalComponent, resolver, options};
this._modalToShow$.next([...this._modalToShow$.getValue(), modalObj]);
promise.then(() => {
@@ -41,7 +41,7 @@ export class ModalService {
export type ModalOptions<T = unknown> = { readonly data?: T, readonly noStyle?: boolean, readonly closable?: boolean }
export type ModalComponent<Return = unknown, Receive = unknown> = ({ resolver, options }: { readonly resolver: (x: ModalResponse<Return>) => void; readonly options?: ModalOptions<Receive> }) => JSX.Element;
export type ModalObject = {modal: ModalComponent, resolver: (value: ModalResponse | PromiseLike<ModalResponse>) => void, options: ModalOptions};
export type ModalObject = {id: string, modal: ModalComponent, resolver: (value: ModalResponse | PromiseLike<ModalResponse>) => void, options: ModalOptions};
export const enum ModalExitCode {
NO_CHOICE = -1,