[FIXED] Compound components pattern with Typescript and React Memo

Issue

I work with compound components and hence assign child components to the parent component itself. It usually looks something like this:

interface ParentComposition {
    Child: typeof SearchCardChild;
}

interface SearchCardProps {}

export const SearchCard: React.FC<SearchCardProps> & ParentComposition = ({}) => {
        return ...;
};

const SearchCardChild: React.FC = () => {
    return ...
}

SearchCard.Child = SearchCardChild;

I’m trying to apply the same pattern to a parent using React.memo, but I keep getting the following error:

Property ‘Child’ is missing in type ‘NamedExoticComponent’ but required in type ‘ParentComposition’.

interface ParentComposition {
    Child: typeof SearchCardChild;
}

interface SearchCardProps {}

export const SearchCard: NamedExoticComponent<SearchCardProps> & ParentComposition = React.memo(({}) => {
        return ...;
});

const SearchCardChild: React.FC = () => {
    return ...
}

SearchCard.Child = SearchCardChild;

How can I do so?

Solution

The composition of components must be after memoization, otherwise property .displayName in BaseForm will cause an error

interface IFormProps extends HTMLAttributes<HTMLDivElement> {}

interface MemoizedFormCompose {
  Item: typeof Item;
}

const BaseForm: FC<IFormProps> = ({ children, className, ...props }) => (
  <div {...props}>
    {children}
  </div>
);

const MemoizedForm = React.memo(BaseForm) as NamedExoticComponent<IFormProps> & MemoizedFormCompose;

MemoizedForm.Item = Item;

export const Form = MemoizedForm;

Answered By – Alexey Masyukov

Answer Checked By – Senaida (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published