diff --git a/packages/cli/package.json b/packages/cli/package.json index 86fc8533bad5b..35faaef116acc 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -68,7 +68,6 @@ "prettier": "^2.7.1", "semver": "7.5.2", "semver-diff": "^3.1.1", - "temp": "^0.9.4", "tslib": "^2.6.2" }, "devDependencies": { @@ -90,7 +89,6 @@ "@types/pluralize": "^0.0.29", "@types/prettier": "^2.7.3", "@types/semver": "^7.5.8", - "@types/temp": "^0.9.1", "@vitest/ui": "^2.1.8", "tsup": "^6.7.0", "typescript": "^5.8.3", diff --git a/packages/cli/src/commands/add/sub-commands/resource/create-resources.ts b/packages/cli/src/commands/add/sub-commands/resource/create-resources.ts index da38518b9d933..87e24ac6c6ed0 100644 --- a/packages/cli/src/commands/add/sub-commands/resource/create-resources.ts +++ b/packages/cli/src/commands/add/sub-commands/resource/create-resources.ts @@ -16,8 +16,9 @@ import { import inquirer from "inquirer"; import { join } from "path"; import { plural } from "pluralize"; -import temp from "temp"; import { getCommandRootDir } from "./get-command-root-dir"; +import { mkdtempSync } from "fs"; +import { tmpdir } from "os"; export const defaultActions = ["list", "create", "edit", "show"]; @@ -134,9 +135,6 @@ export const createResources = async ( } moveSync(tempDir, destinationResourcePath, moveSyncOptions); - // clear temp dir - temp.cleanupSync(); - // if use Next.js, generate page files. This makes easier to use the resource if (isNextJs) { generateNextJsPages( @@ -182,8 +180,7 @@ export const createResources = async ( }; const generateTempDir = (): string => { - temp.track(); - return temp.mkdirSync("resource"); + return mkdtempSync(join(tmpdir(), "resource-")); }; /** diff --git a/packages/core/src/hooks/i18n/useTranslate.ts b/packages/core/src/hooks/i18n/useTranslate.ts index b0888e26e2299..447363bf065d9 100644 --- a/packages/core/src/hooks/i18n/useTranslate.ts +++ b/packages/core/src/hooks/i18n/useTranslate.ts @@ -1,6 +1,7 @@ import { useContext, useMemo } from "react"; import { I18nContext } from "@contexts/i18n"; +import type { UseTranslationProps } from "./useTranslation"; /** * If you need to translate the texts in your own components, refine provides the `useTranslate` hook. @@ -8,7 +9,7 @@ import { I18nContext } from "@contexts/i18n"; * * @see {@link https://refine.dev/docs/api-reference/core/hooks/translate/useTranslate} for more details. */ -export const useTranslate = () => { +export const useTranslate = ({ ns }: UseTranslationProps = {}) => { const { i18nProvider } = useContext(I18nContext); const fn = useMemo(() => { @@ -21,20 +22,37 @@ export const useTranslate = () => { function translate( key: string, - options?: string | any, - defaultMessage?: string, + _options?: string | any, + _defaultMessage?: string, ) { + let options = _options; + let defaultMessage = _defaultMessage; + + if (typeof options === "string" && defaultMessage === undefined) { + defaultMessage = options; + + if (ns) { + options = { ns }; + } else { + options = undefined; + } + } + + if (ns && options && typeof options !== "string") { + options = { ns, ...options }; + } + return ( i18nProvider?.translate(key, options, defaultMessage) ?? defaultMessage ?? - (typeof options === "string" && typeof defaultMessage === "undefined" - ? options + (typeof _options === "string" && typeof _defaultMessage === "undefined" + ? _options : key) ); } return translate; - }, [i18nProvider]); + }, [i18nProvider, ns]); return fn; }; diff --git a/packages/core/src/hooks/i18n/useTranslation.tsx b/packages/core/src/hooks/i18n/useTranslation.tsx index 2d2a5dbb4297e..44b5aa51278f0 100644 --- a/packages/core/src/hooks/i18n/useTranslation.tsx +++ b/packages/core/src/hooks/i18n/useTranslation.tsx @@ -2,6 +2,10 @@ import { useGetLocale } from "./useGetLocale"; import { useSetLocale } from "./useSetLocale"; import { useTranslate } from "./useTranslate"; +export interface UseTranslationProps { + ns?: string | string[]; +} + /** * It combines `useTranslate`, `useSetLocale` and `useGetLocale` hooks for a better developer experience. * It returns `i18nProvider` methods under the hood. @@ -11,8 +15,8 @@ import { useTranslate } from "./useTranslate"; * * @see {@link https://refine.dev/docs/i18n/i18n-provider/} for more details. */ -export const useTranslation = () => { - const translate = useTranslate(); +export const useTranslation = ({ ns }: UseTranslationProps = {}) => { + const translate = useTranslate({ ns }); const changeLocale = useSetLocale(); const getLocale = useGetLocale(); diff --git a/packages/react-hook-form/src/useForm/index.ts b/packages/react-hook-form/src/useForm/index.ts index 99946820a02b6..7f938651925b0 100644 --- a/packages/react-hook-form/src/useForm/index.ts +++ b/packages/react-hook-form/src/useForm/index.ts @@ -129,6 +129,7 @@ export const useForm = < watch, setValue, getValues, + reset, handleSubmit: handleSubmitReactHookForm, setError, formState: { dirtyFields }, @@ -253,39 +254,28 @@ export const useForm = < }); }; - // On query load, attempt a first sync after registration effects run. + // On query load, reset the form with server data natively. + // This ensures useFieldArray and other RHF internals are properly initialized. + const initialLoadRef = React.useRef(true); useEffect(() => { const data = query?.data?.data; if (!data) { queryDataRef.current = undefined; syncedFieldsRef.current = new Set(); mountedFieldsRef.current = new Set(); + initialLoadRef.current = true; return; } - let isActive = true; - - const applyQueryValues = () => { - if (!isActive) return; - - applyValuesToFields(getRegisteredFields(), data, false); - }; - queryDataRef.current = data; - syncedFieldsRef.current = new Set(); mountedFieldsRef.current = getMountedFields(); - // defer until after field registration effects - if (typeof queueMicrotask === "function") { - queueMicrotask(applyQueryValues); - } else { - Promise.resolve().then(applyQueryValues); + if (initialLoadRef.current) { + initialLoadRef.current = false; + syncedFieldsRef.current = new Set(); + reset(data as unknown as TVariables, { keepDirtyValues: true }); } - - return () => { - isActive = false; - }; - }, [query?.data, setValue, getValues]); + }, [query?.data, reset, getValues]); // Re-sync when new fields register; do not override user edits. useEffect(() => { diff --git a/packages/react-router/src/use-document-title.ts b/packages/react-router/src/use-document-title.ts index d17597d3e21fe..b9475d4c1cb39 100644 --- a/packages/react-router/src/use-document-title.ts +++ b/packages/react-router/src/use-document-title.ts @@ -1,26 +1,36 @@ -import { useTranslate } from "@refinedev/core"; -import { useEffect } from "react"; +import { useTranslate, type UseTranslationProps } from "@refinedev/core"; +import { useCallback, useEffect } from "react"; type Title = string | { i18nKey: string }; -export const useDocumentTitle = (title?: Title) => { - const translate = useTranslate(); +interface useDocumentTitleOptions { + ns?: UseTranslationProps["ns"]; + + defaultTitle?: string; +} + +export const useDocumentTitle = ( + title?: Title, + options?: useDocumentTitleOptions, +) => { + const translate = useTranslate({ ns: options?.ns }); + + const getTitle = useCallback( + (title: Title) => { + const key = typeof title === "string" ? title : title.i18nKey; + + return translate(key, options?.defaultTitle); + }, + [translate, options?.defaultTitle], + ); useEffect(() => { if (!title) return; - if (typeof title === "string") { - document.title = translate(title); - } else { - document.title = translate(title.i18nKey); - } - }, [title]); + document.title = getTitle(title); + }, [title, getTitle]); return (title: Title) => { - if (typeof title === "string") { - document.title = translate(title); - } else { - document.title = translate(title.i18nKey); - } + document.title = getTitle(title); }; };