From c3332552d7d7f401d0cde40de120ea43d750c93e Mon Sep 17 00:00:00 2001 From: crbon Date: Thu, 22 Jan 2026 17:27:46 +1000 Subject: [PATCH] refactor(link): simplify LinkEditForm state management and improve slug handling - Removed unnecessary useEffect for slug initialization and replaced it with a more efficient state setup. - Updated handleSubmit to conditionally include the slug in the payload based on link creation or modification. - Enhanced form handling by utilizing watch for dynamic slug updates and improved validation messages for slug input. --- src/app/(main)/links/LinkEditForm.tsx | 78 ++++++++++++++------------- src/components/messages.ts | 2 + 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/app/(main)/links/LinkEditForm.tsx b/src/app/(main)/links/LinkEditForm.tsx index 78000600..2a206920 100644 --- a/src/app/(main)/links/LinkEditForm.tsx +++ b/src/app/(main)/links/LinkEditForm.tsx @@ -10,7 +10,7 @@ import { Row, TextField, } from '@umami/react-zen'; -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { useConfig, useLinkQuery, useMessages } from '@/components/hooks'; import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery'; import { ChevronDown, ChevronRight, RefreshCw } from '@/components/icons'; @@ -42,11 +42,15 @@ export function LinkEditForm({ const { linksUrl } = useConfig(); const hostUrl = linksUrl || LINKS_URL; const { data, isLoading } = useLinkQuery(linkId); - const [slug, setSlug] = useState(generateId()); + const [initialSlug] = useState(() => generateId()); const [showAdvanced, setShowAdvanced] = useState(false); - const handleSubmit = async (data: any) => { - await mutateAsync(data, { + const handleSubmit = async (formData: any) => { + const { slug: formSlug, ...rest } = formData; + // Only include slug if creating new link or if it was modified + const payload = !linkId || formSlug !== data?.slug ? formData : rest; + + await mutateAsync(payload, { onSuccess: async () => { toast(formatMessage(messages.saved)); touch('links'); @@ -56,13 +60,7 @@ export function LinkEditForm({ }); }; - const handleSlug = () => { - const slug = generateId(); - - setSlug(slug); - - return slug; - }; + const handleSlug = () => generateId(); const checkUrl = (url: string) => { if (!isValidUrl(url)) { @@ -71,12 +69,6 @@ export function LinkEditForm({ return true; }; - useEffect(() => { - if (data) { - setSlug(data.slug); - } - }, [data]); - if (linkId && isLoading) { return ; } @@ -85,15 +77,27 @@ export function LinkEditForm({
- {({ setValue }) => { + {({ setValue, watch }) => { + const currentSlug = watch('slug') ?? initialSlug; + return ( <> {formatMessage(labels.link)} - - - { - setSlug(value); - setValue('slug', value, { shouldDirty: true }); - }} - autoComplete="off" - /> - + + + )} diff --git a/src/components/messages.ts b/src/components/messages.ts index a19bf754..ce2bd4e8 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -4,6 +4,8 @@ export const labels = defineMessages({ ok: { id: 'label.ok', defaultMessage: 'OK' }, unknown: { id: 'label.unknown', defaultMessage: 'Unknown' }, required: { id: 'label.required', defaultMessage: 'Required' }, + tooShort: { id: 'label.too-short', defaultMessage: 'Too short' }, + tooLong: { id: 'label.too-long', defaultMessage: 'Too long' }, save: { id: 'label.save', defaultMessage: 'Save' }, cancel: { id: 'label.cancel', defaultMessage: 'Cancel' }, continue: { id: 'label.continue', defaultMessage: 'Continue' },