diff --git a/frontend/src/pages/Settings/Languages/components.tsx b/frontend/src/pages/Settings/Languages/components.tsx index f213e6cd7..7aaf8d906 100644 --- a/frontend/src/pages/Settings/Languages/components.tsx +++ b/frontend/src/pages/Settings/Languages/components.tsx @@ -11,6 +11,7 @@ import { useLatestEnabledLanguages, useLatestProfiles } from "."; import { Selector, SelectorProps } from "../components"; import { useFormActions } from "../utilities/FormValues"; import { BaseInput } from "../utilities/hooks"; +import { useSubmitHookWith } from "../utilities/HooksProvider"; type LanguageSelectorProps = Omit< MultiSelectorProps, @@ -25,6 +26,10 @@ export const LanguageSelector: FunctionComponent< const enabled = useLatestEnabledLanguages(); const { setValue } = useFormActions(); + useSubmitHookWith(settingKey, (value: Language.Info[]) => + value.map((v) => v.code2) + ); + const wrappedOptions = useSelectorOptions(options, (value) => value.name); return ( diff --git a/frontend/src/pages/Settings/Languages/table.tsx b/frontend/src/pages/Settings/Languages/table.tsx index 6e1c82360..339f3fa99 100644 --- a/frontend/src/pages/Settings/Languages/table.tsx +++ b/frontend/src/pages/Settings/Languages/table.tsx @@ -13,6 +13,7 @@ import { Column } from "react-table"; import { useLatestEnabledLanguages, useLatestProfiles } from "."; import { languageProfileKey } from "../keys"; import { useFormActions } from "../utilities/FormValues"; +import { useSubmitHookWith } from "../utilities/HooksProvider"; const Table: FunctionComponent = () => { const profiles = useLatestProfiles(); @@ -26,6 +27,8 @@ const Table: FunctionComponent = () => { [profiles] ); + useSubmitHookWith(languageProfileKey, (value) => JSON.stringify(value)); + const { setValue } = useFormActions(); const modals = useModals(); diff --git a/frontend/src/pages/Settings/utilities/HooksProvider.tsx b/frontend/src/pages/Settings/utilities/HooksProvider.tsx index 2c49f174a..d77da77a2 100644 --- a/frontend/src/pages/Settings/utilities/HooksProvider.tsx +++ b/frontend/src/pages/Settings/utilities/HooksProvider.tsx @@ -1,13 +1,14 @@ +import { LOG } from "@/utilities/console"; import { createContext, FunctionComponent, useCallback, useContext, + useEffect, useMemo, useRef, useState, } from "react"; -import { enabledLanguageKey, languageProfileKey } from "../keys"; // eslint-disable-next-line @typescript-eslint/no-explicit-any type HookType = (value: any) => unknown; @@ -50,20 +51,40 @@ export function useSubmitHooks() { return context; } +export function useSubmitHookWith(key: string, fn?: HookType) { + const fnRef = useRef(fn); + fnRef.current = fn; + + const hooks = useSubmitHooks(); + + useEffect(() => { + const currentFn = fnRef.current; + if (currentFn) { + LOG("info", "Adding submit hook for", key); + hooks.add(key, currentFn); + } + + return () => { + LOG("info", "Removing submit hook for", key); + hooks.remove(key); + }; + }, [key, hooks]); +} + export function useSubmitHooksSource(): SubmitHookModifierType { - const [submitHooks, setSubmitHooks] = useState({ - [languageProfileKey]: (value) => JSON.stringify(value), - [enabledLanguageKey]: (value: Language.Info[]) => value.map((v) => v.code2), - }); + const [submitHooks, setSubmitHooks] = useState({}); const hooksRef = useRef(submitHooks); + hooksRef.current = submitHooks; const invokeHooks = useCallback((settings: LooseObject) => { const hooks = hooksRef.current; for (const key in settings) { if (key in hooks) { + LOG("info", "Running submit hook for", key, settings[key]); const value = settings[key]; const fn = hooks[key]; settings[key] = fn(value); + LOG("info", "Finish submit hook", key, settings[key]); } } }, []); @@ -78,7 +99,10 @@ export function useSubmitHooksSource(): SubmitHookModifierType { const removeHook = useCallback((key: string) => { setSubmitHooks((hooks) => { const newHooks = { ...hooks }; - delete newHooks[key]; + + if (key in newHooks) { + delete newHooks[key]; + } return newHooks; }); diff --git a/frontend/src/pages/Settings/utilities/hooks.ts b/frontend/src/pages/Settings/utilities/hooks.ts index 5f011e7e9..2c6e392da 100644 --- a/frontend/src/pages/Settings/utilities/hooks.ts +++ b/frontend/src/pages/Settings/utilities/hooks.ts @@ -1,13 +1,13 @@ import { LOG } from "@/utilities/console"; import { get, isNull, isUndefined, uniqBy } from "lodash"; -import { useCallback, useEffect, useMemo, useRef } from "react"; +import { useCallback, useMemo, useRef } from "react"; import { FormKey, useFormActions, useStagedValues, } from "../utilities/FormValues"; import { useSettings } from "../utilities/SettingsProvider"; -import { useSubmitHooks } from "./HooksProvider"; +import { useSubmitHookWith } from "./HooksProvider"; export interface BaseInput { disabled?: boolean; @@ -51,23 +51,9 @@ export function useSettingValue( const settings = useSettings(); const optionsRef = useRef(options); + optionsRef.current = options; - const submitHooks = useSubmitHooks(); - - useEffect(() => { - const onSubmit = optionsRef.current?.onSubmit; - if (onSubmit) { - LOG("info", "Adding submit hook for", key); - submitHooks.add(key, onSubmit); - } - - return () => { - if (key in submitHooks) { - LOG("info", "Removing submit hook for", key); - submitHooks.remove(key); - } - }; - }, [key, submitHooks]); + useSubmitHookWith(key, options?.onSubmit); const originalValue = useMemo(() => { const onLoaded = optionsRef.current?.onLoaded;