fix: resolve React hooks order violations in account dialogs

This commit is contained in:
rustmailer
2026-08-19 13:54:13 +08:00
parent ae7a681751
commit 1b2952a6b0
2 changed files with 28 additions and 24 deletions

View File

@@ -25,7 +25,7 @@ import { useToast } from '@/hooks/use-toast';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { ToastAction } from '@/components/ui/toast';
import { AxiosError } from 'axios';
import React from 'react';
import React, { useCallback } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { AccountModel, create_account, update_account } from '@/api/account/api';
@@ -89,19 +89,9 @@ export function NoSyncAccountDialog({ currentRow, open, onOpenChange }: Props) {
const queryClient = useQueryClient();
const createMutation = useMutation({
mutationFn: create_account,
onSuccess: handleSuccess,
onError: handleError,
});
const updateMutation = useMutation({
mutationFn: (data: Record<string, any>) => update_account(currentRow?.id!, data),
onSuccess: handleSuccess,
onError: handleError,
});
function handleSuccess() {
const handleSuccess = useCallback(() => {
toast({
title: isEdit ? t('accounts.accountUpdated') : t('accounts.accountCreated'),
description: isEdit ? t('accounts.accountUpdatedDesc') : t('accounts.accountCreatedDesc'),
@@ -111,9 +101,9 @@ export function NoSyncAccountDialog({ currentRow, open, onOpenChange }: Props) {
queryClient.invalidateQueries({ queryKey: ['account-list'] });
form.reset();
onOpenChange(false);
}
}, [isEdit, t, toast, queryClient, form, onOpenChange]);
function handleError(error: AxiosError) {
const handleError = useCallback((error: AxiosError) => {
const errorMessage =
(error.response?.data as { message?: string })?.message ||
error.message ||
@@ -126,7 +116,19 @@ export function NoSyncAccountDialog({ currentRow, open, onOpenChange }: Props) {
action: <ToastAction altText={t('common.tryAgain')}>{t('common.tryAgain')}</ToastAction>,
});
console.error(error);
}
}, [isEdit, t, toast]);
const createMutation = useMutation({
mutationFn: create_account,
onSuccess: handleSuccess,
onError: handleError,
});
const updateMutation = useMutation({
mutationFn: (data: Record<string, any>) => update_account(currentRow?.id!, data),
onSuccess: handleSuccess,
onError: handleError,
});
const onSubmit = React.useCallback(
(data: NoSyncAccount) => {

View File

@@ -37,17 +37,9 @@ export function RunningStateCellAction({ row }: Props) {
const { setOpen, setCurrentRow } = useAccountContext()
const { require_any_permission } = useCurrentUser()
if (row.original.deleting) {
return <span className="text-xs text-muted-foreground italic">Deleting...</span>
}
let account_type = row.original.account_type;
if (account_type === "NoSync") {
return <span className="text-xs text-muted-foreground">n/a</span>
}
const hasPermission = require_any_permission(['system:root', 'account:read_details'], row.original.id)
// Live sync status pill. While a download session is running, poll every 5s
// so the list always reflects progress without needing the dialog open.
const { data: state } = useQuery({
queryKey: ['running-state', row.original.id],
queryFn: () => download_state(row.original.id),
@@ -56,6 +48,16 @@ export function RunningStateCellAction({ row }: Props) {
return s && s.status === DownloadStatus.Running ? 5000 : false
},
})
if (row.original.deleting) {
return <span className="text-xs text-muted-foreground italic">Deleting...</span>
}
if (row.original.account_type === "NoSync") {
return <span className="text-xs text-muted-foreground">n/a</span>
}
const running = state?.active_session
const isRunning = !!running && running.status === DownloadStatus.Running