From a9ac61133306eccc3ea71492031f965e1e31c3cc Mon Sep 17 00:00:00 2001 From: Junjie <2721795866@qq.com> Date: Tue, 1 Oct 2024 11:01:21 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix(Best=20practice):?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit update react dependency --- src/components/device-overview.tsx | 2 +- src/components/llm/index.tsx | 5 +- src/components/llm/markdown.tsx | 4 +- src/components/organization/profile.tsx | 240 +++++++++++++++--------- src/components/profile-form.tsx | 69 ++++--- src/components/setting-block-config.tsx | 17 +- src/components/supabase-provider.tsx | 20 +- src/hooks/use-block.tsx | 10 +- 8 files changed, 230 insertions(+), 137 deletions(-) diff --git a/src/components/device-overview.tsx b/src/components/device-overview.tsx index e152c0b..0930f49 100644 --- a/src/components/device-overview.tsx +++ b/src/components/device-overview.tsx @@ -101,7 +101,7 @@ export default function DeviceOverview() { const edittingDeviceData = edittingDevice?.data as any; React.useEffect(() => { form.setValue("name", edittingDeviceData?.name || ""); - }, [edittingDeviceData?.name]); + }, [edittingDeviceData?.name, form]); return (
diff --git a/src/components/llm/index.tsx b/src/components/llm/index.tsx index 31b23d2..1a713e4 100644 --- a/src/components/llm/index.tsx +++ b/src/components/llm/index.tsx @@ -250,14 +250,14 @@ export function LLM() { : 2048) || 2048; React.useEffect(() => { if (maxSeqLen < params.maxSeqLen) setParams({ ...params, maxSeqLen }); - }, [maxSeqLen]); + }, [maxSeqLen, params]); const [scrollToBottom, setScrollToBottom] = React.useState(true); const scrollElement = React.useRef(null); React.useEffect(() => { if (scrollToBottom) scrollElement.current?.scrollIntoView({ behavior: "smooth" }); - }, [messages]); + }, [messages, scrollToBottom]); const updateParams = (type: keyof XpModelParams, value: number | string) => { let val = value; @@ -536,6 +536,7 @@ export function LLM() { c.off("xp-llm-recive", f); setChannel(undefined); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const clean = () => { diff --git a/src/components/llm/markdown.tsx b/src/components/llm/markdown.tsx index 0f7f357..36e7cc1 100644 --- a/src/components/llm/markdown.tsx +++ b/src/components/llm/markdown.tsx @@ -70,7 +70,7 @@ function MarkdownTextarea({ } ); } - }, []); + }, [starryNight]); React.useEffect(() => { setText(value); }, [value]); @@ -79,7 +79,7 @@ function MarkdownTextarea({ onChange(text); }, delay); return () => clearTimeout(t); - }, [text]); + }, [delay, onChange, text]); return (
diff --git a/src/components/organization/profile.tsx b/src/components/organization/profile.tsx index 1a1eeda..ecc70ad 100644 --- a/src/components/organization/profile.tsx +++ b/src/components/organization/profile.tsx @@ -1,11 +1,15 @@ "use client"; -import { useOrganizations, useRoles, useSetOrganizations } from "@/hooks/use-organizations"; +import { + useOrganizations, + useRoles, + useSetOrganizations, +} from "@/hooks/use-organizations"; import { useRouter, useSearchParams } from "next/navigation"; import * as React from "react"; -import { zodResolver } from "@hookform/resolvers/zod" -import { useForm } from "react-hook-form" -import { z } from "zod" +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; import { Card, CardContent, @@ -13,7 +17,7 @@ import { CardFooter, CardHeader, CardTitle, -} from "@/components/ui/card" +} from "@/components/ui/card"; import { Form, FormControl, @@ -22,7 +26,7 @@ import { FormItem, FormLabel, FormMessage, -} from "@/components/ui/form" +} from "@/components/ui/form"; import { Dialog, DialogContent, @@ -31,9 +35,13 @@ import { DialogHeader, DialogTitle, DialogTrigger, -} from "@/components/ui/dialog" +} from "@/components/ui/dialog"; import { toast } from "sonner"; -import { deleteOrganization, getCurrentUserOrganizations, updateOrganizationName } from "@/lib/server"; +import { + deleteOrganization, + getCurrentUserOrganizations, + updateOrganizationName, +} from "@/lib/server"; import { useTranslation } from "next-export-i18n"; import { useUserProfile } from "@/hooks/use-user-profile"; import { Input } from "../ui/input"; @@ -41,7 +49,6 @@ import { Button } from "../ui/button"; import { Loader2 } from "lucide-react"; import { Badge } from "../ui/badge"; - export default function Profile() { const { t } = useTranslation(); const userProfile = useUserProfile(); @@ -52,12 +59,15 @@ export default function Profile() { const searchParams = useSearchParams(); const formSchema = z.object({ - name: z.string().min(2, { - message: t("organization.formSchema.name.min"), - }).max(50, { - message: t("organization.formSchema.name.max"), - }) - }) + name: z + .string() + .min(2, { + message: t("organization.formSchema.name.min"), + }) + .max(50, { + message: t("organization.formSchema.name.max"), + }), + }); const [processing, setProcessing] = React.useState(false); // 1. Define form. const form = useForm>({ @@ -65,7 +75,7 @@ export default function Profile() { defaultValues: { name: "", }, - }) + }); const currentOrganization = React.useMemo(() => { const organizationId = searchParams.get("organizationId"); if (organizations && organizationId) { @@ -75,14 +85,15 @@ export default function Profile() { } form.setValue("name", ""); return undefined; - }, [organizations, searchParams]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [organizations, searchParams]); const currentRoles = React.useMemo(() => { const organizationId = searchParams.get("organizationId"); if (roles && organizationId) { return roles.filter((r) => r.organization_id === organizationId); } return []; - }, [roles, searchParams]) + }, [roles, searchParams]); const isOwner = currentRoles.some((r) => r.role_name === "Owner"); // 2. Define a submit handler. @@ -93,10 +104,14 @@ export default function Profile() { const updateOrganization = async (name: string) => { if (isOwner && name && currentOrganization && userProfile) { setProcessing(true); - const { error: error1 } = await updateOrganizationName(currentOrganization.id, name); + const { error: error1 } = await updateOrganizationName( + currentOrganization.id, + name + ); if (!error1) { - toast.success(t('organization.update.success')); - const { data: nextOrganizations, error: error2 } = await getCurrentUserOrganizations(userProfile.id); + toast.success(t("organization.update.success")); + const { data: nextOrganizations, error: error2 } = + await getCurrentUserOrganizations(userProfile.id); if (!error2) { setOrganizations(nextOrganizations); } else { @@ -109,32 +124,48 @@ export default function Profile() { } setProcessing(false); } - } + }; - const regex = React.useMemo(() => new RegExp(`^${currentOrganization?.name}$`), [currentOrganization]) + const regex = React.useMemo( + () => new RegExp(`^${currentOrganization?.name}$`), + [currentOrganization] + ); const deleteFormSchema = z.object({ - name: z.string().regex(regex, { message: t("organization.type_to_confirm", { name: currentOrganization?.name }) }) - }) + name: z.string().regex(regex, { + message: t("organization.type_to_confirm", { + name: currentOrganization?.name, + }), + }), + }); // 1. Define form. const deleteForm = useForm>({ resolver: zodResolver(deleteFormSchema), defaultValues: { name: "", }, - }) + }); function onDeleteSubmit(values: z.infer) { deleteOrganizationAction(values.name); } const deleteOrganizationAction = async (name: string) => { - if (isOwner && name && currentOrganization && name === currentOrganization.name && userProfile) { + if ( + isOwner && + name && + currentOrganization && + name === currentOrganization.name && + userProfile + ) { setProcessing(true); - const { error: error1 } = await deleteOrganization(currentOrganization.id); + const { error: error1 } = await deleteOrganization( + currentOrganization.id + ); if (!error1) { - toast.success(t('organization.delete.success')); - const { data: nextOrganizations, error: error2 } = await getCurrentUserOrganizations(userProfile.id); + toast.success(t("organization.delete.success")); + const { data: nextOrganizations, error: error2 } = + await getCurrentUserOrganizations(userProfile.id); if (!error2) { setOrganizations(nextOrganizations); - router.replace('/organization'); + router.replace("/organization"); } else { toast.error(error2.message); console.log(error2); @@ -145,7 +176,7 @@ export default function Profile() { } setProcessing(false); } - } + }; return (
@@ -163,18 +194,27 @@ export default function Profile() { {t("organization.name")} - {isOwner ? : <>{currentOrganization?.name}} + {isOwner ? ( + + ) : ( + <>{currentOrganization?.name} + )} )} /> - {isOwner && - - } + {isOwner && ( + + + + )} @@ -184,59 +224,79 @@ export default function Profile() { {currentRoles.map((r) => ( - {r.role_name} + + {r.role_name} + ))} - - + - {isOwner && - - {t("organization.danger_action")} - {t("organization.danger_action_description")} - - - - - - - - - - - - {t("organization.delete.name")} - - {t("organization.delete.description")} - - -
- - ( - - {t("organization.name")} - {t("organization.type_to_confirm", { name: currentOrganization?.name })} - - - - - - )} - /> - - - - - -
-
-
-
} + {isOwner && ( + + + {t("organization.danger_action")} + + {t("organization.danger_action_description")} + + + + + + + + + + + + {t("organization.delete.name")} + + {t("organization.delete.description")} + + +
+ + ( + + {t("organization.name")} + + {t("organization.type_to_confirm", { + name: currentOrganization?.name, + })} + + + + + + + )} + /> + + + + + +
+
+
+
+ )}
- ) -} \ No newline at end of file + ); +} diff --git a/src/components/profile-form.tsx b/src/components/profile-form.tsx index 7a770ed..1a467d1 100644 --- a/src/components/profile-form.tsx +++ b/src/components/profile-form.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import { zodResolver } from "@hookform/resolvers/zod" -import { useForm } from "react-hook-form" -import { z } from "zod" +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; -import { Button } from "@/components/ui/button" +import { Button } from "@/components/ui/button"; import { Form, FormControl, @@ -13,14 +13,14 @@ import { FormItem, FormLabel, FormMessage, -} from "@/components/ui/form" -import { Input } from "@/components/ui/input" -import { useTranslation } from "next-export-i18n" -import React from "react" -import { useSetUserProfile, useUserProfile } from "@/hooks/use-user-profile" -import { toast } from "sonner" -import { Loader2 } from "lucide-react" -import { updateUserProfile } from "@/lib/server" +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { useTranslation } from "next-export-i18n"; +import React from "react"; +import { useSetUserProfile, useUserProfile } from "@/hooks/use-user-profile"; +import { toast } from "sonner"; +import { Loader2 } from "lucide-react"; +import { updateUserProfile } from "@/lib/server"; export function ProfileForm() { const { t } = useTranslation(); @@ -28,12 +28,15 @@ export function ProfileForm() { const setUserProfile = useSetUserProfile(); const formSchema = z.object({ - username: z.string().min(2, { - message: t('profile.formSchema.username.min'), - }).max(50, { - message: t('profile.formSchema.username.max'), - }) - }) + username: z + .string() + .min(2, { + message: t("profile.formSchema.username.min"), + }) + .max(50, { + message: t("profile.formSchema.username.max"), + }), + }); const [processing, setProcessing] = React.useState(false); // 1. Define form. const form = useForm>({ @@ -41,14 +44,15 @@ export function ProfileForm() { defaultValues: { username: userProfile?.username, }, - }) + }); React.useEffect(() => { - form.setValue('username', userProfile?.username || ''); + form.setValue("username", userProfile?.username || ""); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [userProfile?.username]); // 2. Define a submit handler. function onSubmit(values: z.infer) { - updateProfile(values.username) + updateProfile(values.username); } const updateProfile = async (username: string) => { @@ -57,19 +61,21 @@ export function ProfileForm() { const { data, error } = await updateUserProfile(userProfile.id, username); if (!error) { setUserProfile(data); - toast.success(t('profile.update.success')); + toast.success(t("profile.update.success")); } else { toast.error(error.message); console.log(error); } setProcessing(false); } - } + }; return (
-

{t('common.profile')}

+

+ {t("common.profile")} +

( - {t('profile.formSchema.username.label')} + {t("profile.formSchema.username.label")} - {t('profile.formSchema.username.description')} + {t("profile.formSchema.username.description")} )} /> - + - ) + ); } diff --git a/src/components/setting-block-config.tsx b/src/components/setting-block-config.tsx index 7d5df94..6f8533a 100644 --- a/src/components/setting-block-config.tsx +++ b/src/components/setting-block-config.tsx @@ -140,7 +140,7 @@ function DefaultBlockRenderer( setObj(nextObj); setQueriedIndex(nextQueriedIndex); }); - }, [block?.block, query]); + }, [block?.block, copy, emptyBlock, query]); const onEdit: ReactJsonViewProps["onEdit"] = (edit) => { console.log(edit); @@ -413,7 +413,20 @@ function SettingBlockConfig({ }); } } - }, [settingsOpened]); + }, [ + blocks.local.access, + blocks.local.block, + blocks.local.id, + blocks.private.access, + blocks.private.block, + blocks.private.id, + copy, + editableBlocks, + emptyBlock, + is_admin, + organizationId, + settingsOpened, + ]); return (
diff --git a/src/components/supabase-provider.tsx b/src/components/supabase-provider.tsx index 82e592f..dfa9c07 100644 --- a/src/components/supabase-provider.tsx +++ b/src/components/supabase-provider.tsx @@ -1,6 +1,6 @@ "use client"; -import { createContext, useEffect } from "react"; +import { createContext, useCallback, useEffect } from "react"; import { useRouter, usePathname } from "next/navigation"; import { useSetUserProfile } from "@/hooks/use-user-profile"; import { @@ -97,7 +97,15 @@ export default function SupabaseProvider({ return () => { subscription.unsubscribe(); }; - }, [router, supabase, session, pathname]); + }, [ + router, + session, + pathname, + setUserProfile, + setOrganizations, + setRoles, + setSession, + ]); useEffect(() => { if (organizations && organizations.length && session?.user.id) @@ -112,9 +120,9 @@ export default function SupabaseProvider({ console.log(error); } }); - }, [supabase, organizations, session]); + }, [organizations, session, setRoles]); - const refreshDevice = () => { + const refreshDevice = useCallback(() => { getDevices().then(({ data, error }) => { if (error) { toast.error(error.message); @@ -123,7 +131,7 @@ export default function SupabaseProvider({ setDevices(data); } }); - }; + }, [setDevices]); useEffect(() => { if (session?.user.id && xpDatas && !xpDatas[session.user.id]) { const userData: XpUserData = { @@ -178,7 +186,7 @@ export default function SupabaseProvider({ refreshDevice(); } } - }, [xpDatas, session?.user.id]); + }, [xpDatas, session?.user?.id, setXpDatas, refreshDevice]); return ( diff --git a/src/hooks/use-block.tsx b/src/hooks/use-block.tsx index 1a00562..37a5c69 100644 --- a/src/hooks/use-block.tsx +++ b/src/hooks/use-block.tsx @@ -54,7 +54,7 @@ export function useSettingBlock( }, }); - const _load = async () => { + const _load = React.useCallback(async () => { if (user?.id) { console.log("loading...", organizationId, applicationKey, blockKey); const { data: publicDate } = await supabase @@ -94,21 +94,21 @@ export function useSettingBlock( local: localData || prev.local, })); } - }; - const load = () => { + }, [applicationKey, blockKey, organizationId, user?.id]); + const load = React.useCallback(() => { if (loading) { return; } setLoading(true); _load().then(() => setLoading(false)); - }; + }, [loading, _load]); React.useEffect(() => { if (organizationId && user?.id) { load(); } - }, [organizationId, user?.id]); + }, [load, organizationId, user?.id]); const mutate = async (block: Block) => { let id = block.id;