HOC Cheatsheet
This HOC Cheatsheet compiles all available knowledge for writing Higher Order Components with React and TypeScript.
- We will map closely to the official docs on HOCs initially
- While hooks exist, many libraries and codebases still have a need to type HOCs.
- Render props may be considered in future
- The goal is to write HOCs that offer type safety while not getting in the way.
Here is a base HOC example you can copy right away:
type PropsAreEqual<P> = (
prevProps: Readonly<P>,
nextProps: Readonly<P>
) => boolean;
const withSampleHoC = <P extends {}>(
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) {
//Do something special to justify the HoC.
return component(props) as JSX.Element;
}
WithSampleHoc.displayName = `withSampleHoC(${componentName})`;
let wrappedComponent = propsAreEqual === false ? WithSampleHoc : React.memo(WithSampleHoc, propsAreEqual);
//copyStaticProperties(component, wrappedComponent);
return wrappedComponent as typeof WithSampleHoc
};
This code meets these criteria:
- Allows a component to return valid elements (
strings | array | boolean | null | number
) and not justJSX.Element | null
. - Wraps it in a memo unless you opt out.
- Removes the nested component, so React Dev tools will just show one component.
- Indicates with
displayName
in React Dev Tool with an annotation that this is a component wrapped in two HoCs - Optional: Copies over static properties that might have been defined on the original component.