fix: use a global cache for custom inputs so they can be accessed anywhere

This commit is contained in:
Josh 2022-12-02 17:23:00 +00:00
parent e3c273cf36
commit 38d13deafa
3 changed files with 46 additions and 11 deletions

View File

@ -9,6 +9,7 @@ import { Stack } from '@strapi/design-system/Stack';
import { useContentTypeLayout } from '../../hooks';
import FieldComponent from '../FieldComponent';
import Inputs from '../Inputs';
import useLazyComponents from '../../hooks/useLazyComponents';
const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, name }) => {
const { getComponentLayout } = useContentTypeLayout();
@ -18,6 +19,8 @@ const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, nam
);
const fields = componentLayoutData.layouts.edit;
const { lazyComponentStore } = useLazyComponents();
return (
<Box
background={isFromDynamicZone ? '' : 'neutral100'}
@ -67,6 +70,7 @@ const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, nam
metadatas={metadatas}
queryInfos={queryInfos}
size={size}
customFieldInputs={lazyComponentStore}
/>
</GridItem>
);

View File

@ -21,6 +21,7 @@ import Preview from './Preview';
import DraggingSibling from './DraggingSibling';
import { CustomIconButton } from './IconButtonCustoms';
import { connect, select } from './utils';
import useLazyComponents from '../../../hooks/useLazyComponents';
const DragButton = styled.span`
display: flex;
@ -177,6 +178,8 @@ const DraggedItem = ({
const accordionTitle = toString(displayedValue);
const accordionHasError = hasErrors ? 'error' : undefined;
const { lazyComponentStore } = useLazyComponents();
return (
<Box ref={refs ? refs.dropRef : null}>
{isDragging && <Preview />}
@ -273,6 +276,7 @@ const DraggedItem = ({
// onBlur={hasErrors ? checkFormErrors : null}
queryInfos={queryInfos}
size={size}
customFieldInputs={lazyComponentStore}
/>
</GridItem>
);

View File

@ -1,42 +1,69 @@
import { useEffect, useState } from 'react';
import { useCustomFields } from '@strapi/helper-plugin';
const componentStore = new Map();
/**
* @description
* A hook to lazy load custom field components
* @param {Array.<string>} componentUids - The uids to look up components
* @returns object
*/
const useLazyComponents = (componentUids) => {
const useLazyComponents = (componentUids = []) => {
const [lazyComponentStore, setLazyComponentStore] = useState({});
const [loading, setLoading] = useState(true);
const customFieldsRegistry = useCustomFields();
useEffect(() => {
const setStore = (store) => {
setLazyComponentStore(store);
setLoading(false);
};
const populateStoreWithCache = () => {
const internalStore = {};
componentStore.forEach((comp, uid) => {
internalStore[uid] = comp;
});
setStore(internalStore);
};
const lazyLoadComponents = async (uids, components) => {
const modules = await Promise.all(components);
const internalStore = {};
uids.forEach((uid, index) => {
if (!Object.keys(lazyComponentStore).includes(uid)) {
setLazyComponentStore({ ...lazyComponentStore, [uid]: modules[index].default });
}
componentStore.set(uid, modules[index].default);
internalStore[uid] = modules[index].default;
});
setStore(internalStore);
};
if (componentUids.length) {
const componentPromises = componentUids.map((uid) => {
/**
* These uids are not in the component store therefore we need to get the components
*/
const newUids = componentUids.filter((uid) => !componentStore.get(uid));
const componentPromises = newUids.map((uid) => {
const customField = customFieldsRegistry.get(uid);
return customField.components.Input();
});
lazyLoadComponents(componentUids, componentPromises);
if (componentPromises.length > 0) {
lazyLoadComponents(newUids, componentPromises);
} else {
populateStoreWithCache();
}
} else if (loading) {
populateStoreWithCache();
}
if (componentUids.length === Object.keys(lazyComponentStore).length) {
setLoading(false);
}
}, [componentUids, customFieldsRegistry, loading, lazyComponentStore]);
}, [componentUids, customFieldsRegistry, loading]);
return { isLazyLoading: loading, lazyComponentStore };
};