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";
|
||||
|
||||
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";
|
||||
|
||||
type Props = { brandId: string };
|
||||
@@ -197,6 +197,10 @@ export default function AbandonedCartDashboard({ brandId }: Props) {
|
||||
|
||||
function CartDetailModal({ cart, onClose }: { cart: AbandonedCart | null; onClose: () => void }) {
|
||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||
const onCloseEvent = useEffectEvent(() => {
|
||||
onClose();
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const dialog = dialogRef.current;
|
||||
if (!dialog) return;
|
||||
@@ -204,13 +208,13 @@ function CartDetailModal({ cart, onClose }: { cart: AbandonedCart | null; onClos
|
||||
if (!cart && dialog.open) dialog.close();
|
||||
const onCancel = (e: Event) => {
|
||||
e.preventDefault();
|
||||
onClose();
|
||||
onCloseEvent();
|
||||
};
|
||||
dialog.addEventListener("cancel", onCancel);
|
||||
return () => {
|
||||
dialog.removeEventListener("cancel", onCancel);
|
||||
};
|
||||
}, [cart, onClose]);
|
||||
}, [cart]);
|
||||
|
||||
if (!cart) return null;
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ export default function BrandSelector({
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
aria-selected={!activeBrand}
|
||||
aria-pressed={!activeBrand}
|
||||
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"
|
||||
style={{
|
||||
@@ -185,7 +185,7 @@ export default function BrandSelector({
|
||||
<li key={b.id}>
|
||||
<button
|
||||
type="button"
|
||||
aria-selected={isActive}
|
||||
aria-pressed={isActive}
|
||||
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"
|
||||
style={{
|
||||
|
||||
@@ -370,7 +370,7 @@ function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
|
||||
<li key={entry.id} className="list-none">
|
||||
<button
|
||||
type="button"
|
||||
aria-selected={isSelected}
|
||||
aria-current={isSelected ? "true" : undefined}
|
||||
onClick={() => navigate(entry.href)}
|
||||
onMouseEnter={() => setSelected(i)}
|
||||
style={{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"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 { createPortal } from "react-dom";
|
||||
|
||||
@@ -140,19 +140,23 @@ export default function ProductFormModal({
|
||||
// parent's React state stays in sync with the native close behavior.
|
||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||
|
||||
const onCloseEvent = useEffectEvent(() => {
|
||||
onClose();
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const dialog = dialogRef.current;
|
||||
if (!dialog) return;
|
||||
if (!dialog.open) dialog.showModal();
|
||||
const onCancel = (e: Event) => {
|
||||
e.preventDefault();
|
||||
onClose();
|
||||
onCloseEvent();
|
||||
};
|
||||
dialog.addEventListener("cancel", onCancel);
|
||||
return () => {
|
||||
dialog.removeEventListener("cancel", onCancel);
|
||||
};
|
||||
}, [open, onClose]);
|
||||
}, [open]);
|
||||
|
||||
const handleFile = useCallback(
|
||||
async (file: File) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"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 Image from "next/image";
|
||||
import { useRouter } from "next/navigation";
|
||||
@@ -390,6 +390,10 @@ function TableView({
|
||||
init();
|
||||
}, []);
|
||||
|
||||
const onDeleteCancelEvent = useEffectEvent(() => {
|
||||
onDeleteCancel();
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!deleteConfirm) return;
|
||||
const dialog = popupDialogRef.current;
|
||||
@@ -397,13 +401,13 @@ function TableView({
|
||||
if (!dialog.open) dialog.showModal();
|
||||
const onCancel = (e: Event) => {
|
||||
e.preventDefault();
|
||||
onDeleteCancel();
|
||||
onDeleteCancelEvent();
|
||||
};
|
||||
dialog.addEventListener("cancel", onCancel);
|
||||
return () => {
|
||||
dialog.removeEventListener("cancel", onCancel);
|
||||
};
|
||||
}, [deleteConfirm, onDeleteCancel]);
|
||||
}, [deleteConfirm]);
|
||||
|
||||
// Track the previous deleteConfirm value so we can adjust menuPos
|
||||
// inline during render when the prop changes — avoids a stale frame
|
||||
|
||||
Reference in New Issue
Block a user