Created
February 7, 2024 10:49
-
-
Save tiagobnobrega/f93c10f1b6dfa49e506976c780ac9f6e to your computer and use it in GitHub Desktop.
React Typescript Subcomponents
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
/** | |
* Attaches subcomponents to a parent component for use in | |
* composed components. Example: | |
* | |
* <Parent> | |
* <Parent.Title>abc</Parent.Title> | |
* <Parent.Body prop1="foobar"/> | |
* </Parent> | |
* | |
* | |
* This function also sets displayname on the parent component | |
* and all children component, and has the correct return type | |
* for typescript. | |
* | |
* Usage: | |
* export const Modal = attachSubComponents( | |
* "Modal", | |
* (props: ModalProps) => { ... }, | |
* { Header, Content, Footer, Title, Subtitle, HeroImage, ... } | |
* ); | |
* @param displayName topLevelComponent's displayName | |
* @param topLevelComponent the parent element of the composed component | |
* @param otherComponents an object of child components (keys are the names of the child components) | |
* @returns the top level component with otherComponents as static properties | |
*/ | |
export function attachSubComponents< | |
C extends React.ComponentType<any>, | |
O extends Record<string, React.ComponentType<any>>, | |
>(displayName: string, topLevelComponent: C, otherComponents: O): C & O { | |
topLevelComponent.displayName = displayName; | |
Object.values(otherComponents).forEach( | |
(component) => | |
(component.displayName = `${displayName}.${component.displayName}`), | |
); | |
return Object.assign(topLevelComponent, otherComponents); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment