fix: react-doctor exhaustive-deps 3→0, prefer-use-effect-event 3→0 (useEffectEvent for modal cancel handlers), role-supports-aria-props 3→0 (aria-pressed/aria-current on buttons)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useCallback, useEffect, useRef } from "react";
|
import { useState, useCallback, useEffect, useRef, useEffectEvent } from "react";
|
||||||
import { getAbandonedCarts, manuallyCloseAbandonedCart, resendAbandonedCartEmail, type AbandonedCart } from "@/actions/email-automation/abandoned-cart";
|
import { getAbandonedCarts, manuallyCloseAbandonedCart, resendAbandonedCartEmail, type AbandonedCart } from "@/actions/email-automation/abandoned-cart";
|
||||||
|
|
||||||
type Props = { brandId: string };
|
type Props = { brandId: string };
|
||||||
@@ -197,6 +197,10 @@ export default function AbandonedCartDashboard({ brandId }: Props) {
|
|||||||
|
|
||||||
function CartDetailModal({ cart, onClose }: { cart: AbandonedCart | null; onClose: () => void }) {
|
function CartDetailModal({ cart, onClose }: { cart: AbandonedCart | null; onClose: () => void }) {
|
||||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||||
|
const onCloseEvent = useEffectEvent(() => {
|
||||||
|
onClose();
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
if (!dialog) return;
|
if (!dialog) return;
|
||||||
@@ -204,13 +208,13 @@ function CartDetailModal({ cart, onClose }: { cart: AbandonedCart | null; onClos
|
|||||||
if (!cart && dialog.open) dialog.close();
|
if (!cart && dialog.open) dialog.close();
|
||||||
const onCancel = (e: Event) => {
|
const onCancel = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClose();
|
onCloseEvent();
|
||||||
};
|
};
|
||||||
dialog.addEventListener("cancel", onCancel);
|
dialog.addEventListener("cancel", onCancel);
|
||||||
return () => {
|
return () => {
|
||||||
dialog.removeEventListener("cancel", onCancel);
|
dialog.removeEventListener("cancel", onCancel);
|
||||||
};
|
};
|
||||||
}, [cart, onClose]);
|
}, [cart]);
|
||||||
|
|
||||||
if (!cart) return null;
|
if (!cart) return null;
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ export default function BrandSelector({
|
|||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-selected={!activeBrand}
|
aria-pressed={!activeBrand}
|
||||||
onClick={() => selectBrand(null)}
|
onClick={() => selectBrand(null)}
|
||||||
className="w-full flex items-center gap-2 px-3 py-2 text-xs text-left transition-colors hover:bg-white/5"
|
className="w-full flex items-center gap-2 px-3 py-2 text-xs text-left transition-colors hover:bg-white/5"
|
||||||
style={{
|
style={{
|
||||||
@@ -185,7 +185,7 @@ export default function BrandSelector({
|
|||||||
<li key={b.id}>
|
<li key={b.id}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-selected={isActive}
|
aria-pressed={isActive}
|
||||||
onClick={() => selectBrand(b.id)}
|
onClick={() => selectBrand(b.id)}
|
||||||
className="w-full flex items-center gap-2 px-3 py-2 text-xs text-left transition-colors hover:bg-white/5"
|
className="w-full flex items-center gap-2 px-3 py-2 text-xs text-left transition-colors hover:bg-white/5"
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
|
|||||||
<li key={entry.id} className="list-none">
|
<li key={entry.id} className="list-none">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-selected={isSelected}
|
aria-current={isSelected ? "true" : undefined}
|
||||||
onClick={() => navigate(entry.href)}
|
onClick={() => navigate(entry.href)}
|
||||||
onMouseEnter={() => setSelected(i)}
|
onMouseEnter={() => setSelected(i)}
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
|
import { useCallback, useEffect, useRef, useState, useSyncExternalStore, useEffectEvent } from "react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
|
|
||||||
@@ -140,19 +140,23 @@ export default function ProductFormModal({
|
|||||||
// parent's React state stays in sync with the native close behavior.
|
// parent's React state stays in sync with the native close behavior.
|
||||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||||
|
|
||||||
|
const onCloseEvent = useEffectEvent(() => {
|
||||||
|
onClose();
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
if (!dialog) return;
|
if (!dialog) return;
|
||||||
if (!dialog.open) dialog.showModal();
|
if (!dialog.open) dialog.showModal();
|
||||||
const onCancel = (e: Event) => {
|
const onCancel = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClose();
|
onCloseEvent();
|
||||||
};
|
};
|
||||||
dialog.addEventListener("cancel", onCancel);
|
dialog.addEventListener("cancel", onCancel);
|
||||||
return () => {
|
return () => {
|
||||||
dialog.removeEventListener("cancel", onCancel);
|
dialog.removeEventListener("cancel", onCancel);
|
||||||
};
|
};
|
||||||
}, [open, onClose]);
|
}, [open]);
|
||||||
|
|
||||||
const handleFile = useCallback(
|
const handleFile = useCallback(
|
||||||
async (file: File) => {
|
async (file: File) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useCallback, useTransition, useEffect, useRef } from "react";
|
import { useState, useCallback, useTransition, useEffect, useRef, useEffectEvent } from "react";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
@@ -390,6 +390,10 @@ function TableView({
|
|||||||
init();
|
init();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const onDeleteCancelEvent = useEffectEvent(() => {
|
||||||
|
onDeleteCancel();
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!deleteConfirm) return;
|
if (!deleteConfirm) return;
|
||||||
const dialog = popupDialogRef.current;
|
const dialog = popupDialogRef.current;
|
||||||
@@ -397,13 +401,13 @@ function TableView({
|
|||||||
if (!dialog.open) dialog.showModal();
|
if (!dialog.open) dialog.showModal();
|
||||||
const onCancel = (e: Event) => {
|
const onCancel = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onDeleteCancel();
|
onDeleteCancelEvent();
|
||||||
};
|
};
|
||||||
dialog.addEventListener("cancel", onCancel);
|
dialog.addEventListener("cancel", onCancel);
|
||||||
return () => {
|
return () => {
|
||||||
dialog.removeEventListener("cancel", onCancel);
|
dialog.removeEventListener("cancel", onCancel);
|
||||||
};
|
};
|
||||||
}, [deleteConfirm, onDeleteCancel]);
|
}, [deleteConfirm]);
|
||||||
|
|
||||||
// Track the previous deleteConfirm value so we can adjust menuPos
|
// Track the previous deleteConfirm value so we can adjust menuPos
|
||||||
// inline during render when the prop changes — avoids a stale frame
|
// inline during render when the prop changes — avoids a stale frame
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef, useEffectEvent } from "react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { LotDetail } from "@/actions/route-trace/lots";
|
import { LotDetail } from "@/actions/route-trace/lots";
|
||||||
|
|
||||||
@@ -91,16 +91,20 @@ export default function StickerPreviewModal({ lot, onClose }: { lot: LotDetail;
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const onCloseEvent = useEffectEvent(() => {
|
||||||
|
onClose();
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
if (!dialog) return;
|
if (!dialog) return;
|
||||||
const handleCancel = (e: Event) => {
|
const handleCancel = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClose();
|
onCloseEvent();
|
||||||
};
|
};
|
||||||
dialog.addEventListener("cancel", handleCancel);
|
dialog.addEventListener("cancel", handleCancel);
|
||||||
return () => dialog.removeEventListener("cancel", handleCancel);
|
return () => dialog.removeEventListener("cancel", handleCancel);
|
||||||
}, [onClose]);
|
}, []);
|
||||||
|
|
||||||
const handleBackdropClick = (e: React.MouseEvent) => {
|
const handleBackdropClick = (e: React.MouseEvent) => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef, useEffectEvent } from "react";
|
||||||
import { type WholesaleOrder, recordWholesaleDeposit } from "@/actions/wholesale";
|
import { type WholesaleOrder, recordWholesaleDeposit } from "@/actions/wholesale";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -26,16 +26,20 @@ export default function DepositModal({ order, onClose, onFulfilled }: Props) {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const onCloseEvent = useEffectEvent(() => {
|
||||||
|
onClose();
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
if (!dialog) return;
|
if (!dialog) return;
|
||||||
const handleCancel = (e: Event) => {
|
const handleCancel = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClose();
|
onCloseEvent();
|
||||||
};
|
};
|
||||||
dialog.addEventListener("cancel", handleCancel);
|
dialog.addEventListener("cancel", handleCancel);
|
||||||
return () => dialog.removeEventListener("cancel", handleCancel);
|
return () => dialog.removeEventListener("cancel", handleCancel);
|
||||||
}, [onClose]);
|
}, []);
|
||||||
|
|
||||||
const handleBackdropClick = (e: React.MouseEvent) => {
|
const handleBackdropClick = (e: React.MouseEvent) => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef, useEffectEvent } from "react";
|
||||||
import { type WholesaleOrder } from "@/actions/wholesale";
|
import { type WholesaleOrder } from "@/actions/wholesale";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -38,16 +38,20 @@ export default function OrderDetailsModal({ order, onClose, onFulfill, onRecordD
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const onCloseEvent = useEffectEvent(() => {
|
||||||
|
onClose();
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
if (!dialog) return;
|
if (!dialog) return;
|
||||||
const handleCancel = (e: Event) => {
|
const handleCancel = (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClose();
|
onCloseEvent();
|
||||||
};
|
};
|
||||||
dialog.addEventListener("cancel", handleCancel);
|
dialog.addEventListener("cancel", handleCancel);
|
||||||
return () => dialog.removeEventListener("cancel", handleCancel);
|
return () => dialog.removeEventListener("cancel", handleCancel);
|
||||||
}, [onClose]);
|
}, []);
|
||||||
|
|
||||||
const handleBackdropClick = (e: React.MouseEvent) => {
|
const handleBackdropClick = (e: React.MouseEvent) => {
|
||||||
const dialog = dialogRef.current;
|
const dialog = dialogRef.current;
|
||||||
|
|||||||
Reference in New Issue
Block a user