import { isEqual } from 'lodash'; import React, { useCallback, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { createSelector } from 'reselect'; import AppState from 'App/State/AppState'; import ProviderOptionsAppState, { ProviderOptions, } from 'App/State/ProviderOptionsAppState'; import usePrevious from 'Helpers/Hooks/usePrevious'; import { clearOptions, fetchOptions, } from 'Store/Actions/providerOptionActions'; import { FieldSelectOption } from 'typings/Field'; import EnhancedSelectInput, { EnhancedSelectInputProps, EnhancedSelectInputValue, } from './EnhancedSelectInput'; const importantFieldNames = ['baseUrl', 'apiPath', 'apiKey', 'authToken']; function getProviderDataKey(providerData: ProviderOptions) { if (!providerData || !providerData.fields) { return null; } const fields = providerData.fields .filter((f) => importantFieldNames.includes(f.name)) .map((f) => f.value); return fields; } function getSelectOptions(items: FieldSelectOption[]) { if (!items) { return []; } return items.map((option) => { return { key: option.value, value: option.name, hint: option.hint, parentKey: option.parentValue, isDisabled: option.isDisabled, additionalProperties: option.additionalProperties, }; }); } function createProviderOptionsSelector( selectOptionsProviderAction: keyof Omit ) { return createSelector( (state: AppState) => state.providerOptions[selectOptionsProviderAction], (options) => { if (!options) { return { isFetching: false, values: [], }; } return { isFetching: options.isFetching, values: getSelectOptions(options.items), }; } ); } interface ProviderOptionSelectInputProps extends Omit< EnhancedSelectInputProps, unknown>, 'values' > { provider: string; providerData: ProviderOptions; name: string; value: unknown; selectOptionsProviderAction: keyof Omit; } function ProviderOptionSelectInput({ provider, providerData, selectOptionsProviderAction, ...otherProps }: ProviderOptionSelectInputProps) { const dispatch = useDispatch(); const [isRefetchRequired, setIsRefetchRequired] = useState(false); const previousProviderData = usePrevious(providerData); const { isFetching, values } = useSelector( createProviderOptionsSelector(selectOptionsProviderAction) ); const handleOpen = useCallback(() => { if (isRefetchRequired && selectOptionsProviderAction) { setIsRefetchRequired(false); dispatch( fetchOptions({ section: selectOptionsProviderAction, action: selectOptionsProviderAction, provider, providerData, }) ); } }, [ isRefetchRequired, provider, providerData, selectOptionsProviderAction, dispatch, ]); useEffect(() => { if (selectOptionsProviderAction) { dispatch( fetchOptions({ section: selectOptionsProviderAction, action: selectOptionsProviderAction, provider, providerData, }) ); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectOptionsProviderAction, dispatch]); useEffect(() => { if (!previousProviderData) { return; } const prevKey = getProviderDataKey(previousProviderData); const nextKey = getProviderDataKey(providerData); if (!isEqual(prevKey, nextKey)) { setIsRefetchRequired(true); } }, [providerData, previousProviderData, setIsRefetchRequired]); useEffect(() => { return () => { if (selectOptionsProviderAction) { dispatch(clearOptions({ section: selectOptionsProviderAction })); } }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( ); } export default ProviderOptionSelectInput;