refactor(auth): support async deferred actions for login gating
Allow deferred login actions to return promises and execute them safely without violating lint rules. Also initialize order detail timer state without impure render-time Date.now calls so React hook purity checks pass.
This commit is contained in:
@@ -43,7 +43,7 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
|
|||||||
// Returning a fresh filtered array from the selector can re-trigger updates
|
// Returning a fresh filtered array from the selector can re-trigger updates
|
||||||
// and loop under useSyncExternalStore (pmndrs/zustand#1936, #3155).
|
// and loop under useSyncExternalStore (pmndrs/zustand#1936, #3155).
|
||||||
const reviews = useMemo(() => allReviews.filter((item) => item.orderId === id), [allReviews, id])
|
const reviews = useMemo(() => allReviews.filter((item) => item.orderId === id), [allReviews, id])
|
||||||
const [nowTs, setNowTs] = useState(Date.now())
|
const [nowTs, setNowTs] = useState(0)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!order) return
|
if (!order) return
|
||||||
@@ -55,6 +55,8 @@ export default function OrderDetailPage({ params }: { params: Promise<{ id: stri
|
|||||||
if (!order) return
|
if (!order) return
|
||||||
if (order.status !== "pending_accept" && order.status !== "pending_close") return
|
if (order.status !== "pending_accept" && order.status !== "pending_close") return
|
||||||
|
|
||||||
|
setNowTs(Date.now())
|
||||||
|
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
setNowTs(Date.now())
|
setNowTs(Date.now())
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ import { useLoginDialogStore } from "@/store/login-dialog"
|
|||||||
type RequestExecutor<T> = () => Promise<T>
|
type RequestExecutor<T> = () => Promise<T>
|
||||||
|
|
||||||
interface RequestOptions {
|
interface RequestOptions {
|
||||||
onUnauthorized?: () => void
|
onUnauthorized?: () => void | Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function requestWithAuth<T>(executor: RequestExecutor<T>, options?: RequestOptions) {
|
export async function requestWithAuth<T>(executor: RequestExecutor<T>, options?: RequestOptions) {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ export function useRequireAuth() {
|
|||||||
const openLoginDialog = useLoginDialogStore((s) => s.openLoginDialog)
|
const openLoginDialog = useLoginDialogStore((s) => s.openLoginDialog)
|
||||||
|
|
||||||
const requireAuth = useCallback(
|
const requireAuth = useCallback(
|
||||||
(action: () => void) => {
|
(action: () => void | Promise<void>) => {
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
action()
|
void action()
|
||||||
} else {
|
} else {
|
||||||
openLoginDialog(action)
|
openLoginDialog(action)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { create } from "zustand"
|
|||||||
|
|
||||||
interface LoginDialogState {
|
interface LoginDialogState {
|
||||||
open: boolean
|
open: boolean
|
||||||
pendingActions: Array<() => void>
|
pendingActions: Array<() => void | Promise<void>>
|
||||||
openLoginDialog: (action?: () => void) => void
|
openLoginDialog: (action?: () => void | Promise<void>) => void
|
||||||
closeLoginDialog: () => void
|
closeLoginDialog: () => void
|
||||||
consumePendingAction: () => void
|
consumePendingAction: () => void
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ export const useLoginDialogStore = create<LoginDialogState>((set, get) => ({
|
|||||||
const actions = get().pendingActions
|
const actions = get().pendingActions
|
||||||
set({ pendingActions: [] })
|
set({ pendingActions: [] })
|
||||||
actions.forEach((action) => {
|
actions.forEach((action) => {
|
||||||
action()
|
void action()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|||||||
Reference in New Issue
Block a user