Fix custom field input loader remounting

This commit is contained in:
Rémi de Juvigny 2022-08-18 11:28:30 +02:00
parent 1fed0afa01
commit 6e3b2d683a
3 changed files with 24 additions and 40 deletions

View File

@ -1,4 +1,4 @@
import React, { useRef } from 'react';
import React from 'react';
import { Stack } from '@strapi/design-system/Stack';
import { FieldHint, FieldError, FieldLabel } from '@strapi/design-system/Field';
import { useIntl } from 'react-intl';
@ -15,17 +15,13 @@ const ColorPickerInput = ({
}) => {
const { formatMessage } = useIntl();
const renderCount = useRef(0);
renderCount.current += 1;
console.log('renderCount', renderCount.current);
return (
<div>
<Stack spacing={1}>
<FieldLabel action={labelAction} name={name} required={required} htmlFor={id || name}>
{formatMessage(intlLabel)}
</FieldLabel>
<input type="text" id={id || name} name={name} value={value} onChange={onChange} />
<input type="color" id={id || name} name={name} value={value} onChange={onChange} />
<FieldHint />
<FieldError />
</Stack>

View File

@ -1,14 +0,0 @@
import React, { useMemo, memo } from 'react';
import PropTypes from 'prop-types';
const InputLoader = ({ component, ...props }) => {
const LazyComponent = useMemo(() => React.lazy(component), [component]);
return <LazyComponent {...props} />;
};
InputLoader.propTypes = {
component: PropTypes.func.isRequired,
};
export default memo(InputLoader);

View File

@ -1,4 +1,4 @@
import React, { memo, Suspense, useMemo } from 'react';
import React, { Suspense, memo, useMemo } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import get from 'lodash/get';
@ -27,7 +27,6 @@ import {
select,
VALIDATIONS_TO_OMIT,
} from './utils';
import InputLoader from './InputLoader';
function Inputs({
allowedFields,
@ -172,6 +171,19 @@ function Inputs({
const { label, description, placeholder, visible } = metadatas;
// Memoize the component to avoid remounting it and losing state
const CustomFieldInput = useMemo(() => {
if (customFieldUid) {
const customField = customFieldsRegistry.get(customFieldUid);
const CustomFieldInput = React.lazy(customField.components.Input);
return CustomFieldInput;
}
// Not a custom field, component won't be used
return null;
}, [customFieldUid, customFieldsRegistry]);
if (visible === false) {
return null;
}
@ -225,23 +237,6 @@ function Inputs({
);
}
const customInputs = {
json: InputJSON,
uid: InputUID,
media: fields.media,
wysiwyg: Wysiwyg,
...fields,
};
if (customFieldUid) {
const customField = customFieldsRegistry.get(customFieldUid);
// const CustomFieldInput = TestColorPicker;
const CustomFieldInput = (props) => (
<InputLoader component={customField.components.Input} {...props} />
);
customInputs[customFieldUid] = CustomFieldInput;
}
return (
<Suspense fallback={<LoadingIndicatorPage />}>
<GenericInput
@ -256,7 +251,14 @@ function Inputs({
labelAction={labelAction}
contentTypeUID={currentContentTypeLayout.uid}
customFieldUid={customFieldUid}
customInputs={customInputs}
customInputs={{
json: InputJSON,
uid: InputUID,
media: fields.media,
wysiwyg: Wysiwyg,
[customFieldUid]: CustomFieldInput,
...fields,
}}
multiple={fieldSchema.multiple || false}
name={keys}
onChange={onChange}