Add new hook useSubmitHookWith to dynamically inject the submit hooks #1924

This commit is contained in:
LASER-Yi 2022-10-25 23:39:57 +08:00
parent c08ba5f793
commit 1766ceeabc
4 changed files with 42 additions and 24 deletions

View File

@ -11,6 +11,7 @@ import { useLatestEnabledLanguages, useLatestProfiles } from ".";
import { Selector, SelectorProps } from "../components"; import { Selector, SelectorProps } from "../components";
import { useFormActions } from "../utilities/FormValues"; import { useFormActions } from "../utilities/FormValues";
import { BaseInput } from "../utilities/hooks"; import { BaseInput } from "../utilities/hooks";
import { useSubmitHookWith } from "../utilities/HooksProvider";
type LanguageSelectorProps = Omit< type LanguageSelectorProps = Omit<
MultiSelectorProps<Language.Info>, MultiSelectorProps<Language.Info>,
@ -25,6 +26,10 @@ export const LanguageSelector: FunctionComponent<
const enabled = useLatestEnabledLanguages(); const enabled = useLatestEnabledLanguages();
const { setValue } = useFormActions(); const { setValue } = useFormActions();
useSubmitHookWith(settingKey, (value: Language.Info[]) =>
value.map((v) => v.code2)
);
const wrappedOptions = useSelectorOptions(options, (value) => value.name); const wrappedOptions = useSelectorOptions(options, (value) => value.name);
return ( return (

View File

@ -13,6 +13,7 @@ import { Column } from "react-table";
import { useLatestEnabledLanguages, useLatestProfiles } from "."; import { useLatestEnabledLanguages, useLatestProfiles } from ".";
import { languageProfileKey } from "../keys"; import { languageProfileKey } from "../keys";
import { useFormActions } from "../utilities/FormValues"; import { useFormActions } from "../utilities/FormValues";
import { useSubmitHookWith } from "../utilities/HooksProvider";
const Table: FunctionComponent = () => { const Table: FunctionComponent = () => {
const profiles = useLatestProfiles(); const profiles = useLatestProfiles();
@ -26,6 +27,8 @@ const Table: FunctionComponent = () => {
[profiles] [profiles]
); );
useSubmitHookWith(languageProfileKey, (value) => JSON.stringify(value));
const { setValue } = useFormActions(); const { setValue } = useFormActions();
const modals = useModals(); const modals = useModals();

View File

@ -1,13 +1,14 @@
import { LOG } from "@/utilities/console";
import { import {
createContext, createContext,
FunctionComponent, FunctionComponent,
useCallback, useCallback,
useContext, useContext,
useEffect,
useMemo, useMemo,
useRef, useRef,
useState, useState,
} from "react"; } from "react";
import { enabledLanguageKey, languageProfileKey } from "../keys";
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
type HookType = (value: any) => unknown; type HookType = (value: any) => unknown;
@ -50,20 +51,40 @@ export function useSubmitHooks() {
return context; 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 { export function useSubmitHooksSource(): SubmitHookModifierType {
const [submitHooks, setSubmitHooks] = useState<SubmitHookType>({ const [submitHooks, setSubmitHooks] = useState<SubmitHookType>({});
[languageProfileKey]: (value) => JSON.stringify(value),
[enabledLanguageKey]: (value: Language.Info[]) => value.map((v) => v.code2),
});
const hooksRef = useRef(submitHooks); const hooksRef = useRef(submitHooks);
hooksRef.current = submitHooks;
const invokeHooks = useCallback((settings: LooseObject) => { const invokeHooks = useCallback((settings: LooseObject) => {
const hooks = hooksRef.current; const hooks = hooksRef.current;
for (const key in settings) { for (const key in settings) {
if (key in hooks) { if (key in hooks) {
LOG("info", "Running submit hook for", key, settings[key]);
const value = settings[key]; const value = settings[key];
const fn = hooks[key]; const fn = hooks[key];
settings[key] = fn(value); 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) => { const removeHook = useCallback((key: string) => {
setSubmitHooks((hooks) => { setSubmitHooks((hooks) => {
const newHooks = { ...hooks }; const newHooks = { ...hooks };
delete newHooks[key];
if (key in newHooks) {
delete newHooks[key];
}
return newHooks; return newHooks;
}); });

View File

@ -1,13 +1,13 @@
import { LOG } from "@/utilities/console"; import { LOG } from "@/utilities/console";
import { get, isNull, isUndefined, uniqBy } from "lodash"; import { get, isNull, isUndefined, uniqBy } from "lodash";
import { useCallback, useEffect, useMemo, useRef } from "react"; import { useCallback, useMemo, useRef } from "react";
import { import {
FormKey, FormKey,
useFormActions, useFormActions,
useStagedValues, useStagedValues,
} from "../utilities/FormValues"; } from "../utilities/FormValues";
import { useSettings } from "../utilities/SettingsProvider"; import { useSettings } from "../utilities/SettingsProvider";
import { useSubmitHooks } from "./HooksProvider"; import { useSubmitHookWith } from "./HooksProvider";
export interface BaseInput<T> { export interface BaseInput<T> {
disabled?: boolean; disabled?: boolean;
@ -51,23 +51,9 @@ export function useSettingValue<T>(
const settings = useSettings(); const settings = useSettings();
const optionsRef = useRef(options); const optionsRef = useRef(options);
optionsRef.current = options;
const submitHooks = useSubmitHooks(); useSubmitHookWith(key, options?.onSubmit);
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]);
const originalValue = useMemo(() => { const originalValue = useMemo(() => {
const onLoaded = optionsRef.current?.onLoaded; const onLoaded = optionsRef.current?.onLoaded;