Skip to content
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useState, useMemo, useCallback, ReactNode } from "react";
import { useState, useMemo, useCallback, useEffect, useRef, ReactNode } from "react";
import { Check } from "lucide-react";
import { useTranslations } from "next-intl";
import { Input } from "@/components/input";
Expand Down Expand Up @@ -72,6 +72,17 @@ export function SelectModal({
}: SelectModalProps) {
const t = useTranslations("selectModal");
const [searchQuery, setSearchQuery] = useState("");
// Guard against rapid double-clicks: once a selection fires, ignore any
// subsequent clicks until the dialog has closed and re-opened.
const isSelectingRef = useRef(false);

// Reset the guard whenever the modal opens so it's ready for the next session.
useEffect(() => {
if (isOpen) {
isSelectingRef.current = false;
}
}, [isOpen]);
Comment on lines +79 to +84

const effectiveSearchPlaceholder = searchPlaceholder ?? t("searchByName");

const filteredOptions = useMemo(() => {
Expand Down Expand Up @@ -109,6 +120,13 @@ export function SelectModal({

const handleSelect = useCallback(
(option: SelectOption) => {
// Prevent a rapid double-click from triggering the handler twice.
// The second click would otherwise call onSelect again while the
// modal's close animation is still running, causing a flicker where
// the modal briefly reopens.
if (isSelectingRef.current) return;
isSelectingRef.current = true;

Comment thread
frol marked this conversation as resolved.
Outdated
onSelect(option);
if (!multiSelect) {
setSearchQuery("");
Expand Down
Loading