Skip to content

Instantly share code, notes, and snippets.

@karol-majewski
Created December 20, 2022 16:08
Show Gist options
  • Save karol-majewski/6d61fb7d42513d97c26f9d633608f392 to your computer and use it in GitHub Desktop.
Save karol-majewski/6d61fb7d42513d97c26f9d633608f392 to your computer and use it in GitHub Desktop.
Higher-order adapter for react-aria components used inside Ant Design forms
import React from 'react';
import { Form } from 'antd';
import { ValidationState } from '@react-types/shared';
type PropsAreEqual<P> = (prevProps: Readonly<P>, nextProps: Readonly<P>) => boolean;
/**
* When the wrapped component is placed inside an Ant Design form, this higher-order component
* will grab the validation status from the nearest form field and translate it to `ValidationState`.
*
* HOC template from @link https://react-typescript-cheatsheet.netlify.app/docs/hoc/
*/
export function withValidationState<P extends { validationState?: ValidationState }>(
component: {
(props: P): Exclude<React.ReactNode, undefined>;
displayName?: string;
},
propsAreEqual?: PropsAreEqual<P> | false,
componentName = component.displayName ?? component.name
): {
(props: P): JSX.Element;
displayName: string;
} {
function WithSampleHoc(props: P) {
const { status } = Form.Item.useStatus();
const validationState = (() => {
switch (status) {
case 'error':
case 'warning':
return 'invalid';
case 'success':
return 'valid';
case 'validating':
default:
return undefined;
}
})();
return component({ validationState, ...props }) as JSX.Element;
}
WithSampleHoc.displayName = `withSampleHoC(${componentName})`;
const wrappedComponent = propsAreEqual === false ? WithSampleHoc : React.memo(WithSampleHoc, propsAreEqual);
return wrappedComponent as typeof WithSampleHoc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment