Component Structure
Overview
General
Notes:
Only 1 exported function per component file (the main/"exported" component)
If needing to reuse a local component/function/variable/type in another file, it should then be be moved to their own file at that time (and moved to their proper location)
Use
Props
as the name for exported component's interface/typeFor additional local components, append "Props" to the local component name
LocalComponentNameProps
Destructure top-level props within signature (vs first line destructuring)
Then, use first-line destructuring for destructuring individual top-level props when needed
// ...
// ...
// ...
Template
// Imports
// Constants (Preference 1)
interface Props {}
export function ComponentName({}: Props) {
// Constants (Preference 2)
// Hooks
// State
// Effects
// Functions (Preference 2)
// Constants (Preference 3) (e.g. variables that depend on local state/effects)
// Render Logic (e.g. isLoading, isError, isDisabled, etc.)
return (
<>
{/* Render */}
</>
);
}
// Functions (Preference 1)
// - Components (first)
// - Functions (second)
Example
See MUI Styled Components example
MUI styled components
When creating a utility/reusable component with an MUI component as the "base" component:
.
Props
interface should extend the MUI component's native props
import { Button, type ButtonProps } from '@mui/material'
interface Props extends ButtonProps {...}
Destructure the
sx
prop from...props
(within the component signature/declaration)
export function MuiComponentAdjective({ sx, ...props }: Props) {
...
}
Pass in the destructured
sx
prop into the MuiComponent's sx prop after any "default" sx stylingOtherwise, passing the
sx
prop to an instance of the MuiComponent will override any "default"sx
prop styling that exists
export function MuiComponentAdjective({ sx, ...props }: Props) {
<MuiComponent
sx={{
// any "default" sx styling for styled MUI component
...sx
}}
{...props}
>
}
Template
import { MuiComponent, type MuiComponentProps } from '@mui/material';
interface Props extends MuiComponentProps {
// any unique fields that are not included within MuiComponentProps (aka not a native prop to the MuiComponent)
}
export function MuiComponentAdjective({ uniqueField, sx, ...props }: Props) {
return (
<>
<MuiComponent
// data-testid="muicomponent-adjective" (when needed for testing)
// any "default" props for styled MUI component
sx={{
// any "default" sx styling for styled MUI component
...sx, // allows overriding of "default" sx styling (e.g. scenario where changing the margin would result in better aesthetics on a specific instance of MuiComponentAdjective
}}
{...props} // allows overriding of "default" props
>
{...}
</MuiComponent>
</>
);
}
Example
import { IconButton, type IconButtonProps } from '@mui/material';
import { Icon } from './Icon';
interface Props extends IconButtonProps {
handleClose: () => void;
}
export function IconButtonClose({ handleClose, sx, props }: Props) {
return (
<>
<IconButton
data-testid="button-close"
color="inherit"
size="small"
onClick={() => handleClose()}
edge="end"
sx={{
opacity: 0.6,
...sx,
}}
{...props}
>
<Icon icon="close" />
</IconButton>
</>
);
}
Last updated