Component Composition Through Property Attachment
In React applications, complex interfaces are often broken down into smaller, reusable pieces. A common pattern involves creating parent cmoponents that serve as containers for related child components. This approach improves code organization and maintainability.
Implementation Approach
The following example demonstrates how to create a navigation menu system where the main Navbar component contains multiple Link sub-components.
// components/Navbar/index.jsx
import React from 'react';
function Navbar({ contents }) {
return (
<header style={{
background: '#2c3e50',
padding: '12px',
display: 'flex',
spacing: '20px'
}}>
{contents}
</header>
);
}
function Link({ label }) {
return (
<span
style={{
color: '#ecf0f1',
textDecoration: 'none',
padding: '8px 12px'
}}
>
{label}
</span>
);
}
// Attach child component as property
Navbar.Link = Link;
export default Navbar;
Component Usage
After defining the component structure, import and use it in your application:
// App.jsx
import React from 'react';
import Navbar from './components/Navbar';
function Application() {
return (
<div style={{ margin: '25px' }}>
<h1>Web Portal</h1>
<Navbar>
<Navbar.Link label="Dashboard" />
<Navbar.Link label="Services" />
<Navbar.Link label="Documentation" />
<Navbar.Link label="Support" />
</Navbar>
</div>
);
}
export default Application;
Aletrnative Organization Methods
While individual exports are possible:
// Separate export approach
export function Navbar() { /* implementation */ }
export function NavLink() { /* implementation */ }
// Usage requires multiple imports
import { Navbar, NavLink } from './components/Navbar';
The property attachment method offers several advantages:
- Clear semantic relationship between componants
- Namespace isolation preventing naming collisions
- Intuitive usage pattern matching real-world hierarchies
Extended Example: Profile Card
A more comprehensive example shows a user profile component with avatar and details sections:
// components/ProfileCard/index.jsx
import React from 'react';
function ProfileCard({ elements }) {
return (
<section style={{
border: '1px solid #bdc3c7',
borderRadius: '10px',
padding: '18px',
maxWidth: '350px'
}}>
{elements}
</section>
);
}
function Picture({ url, description }) {
return (
<img
src={url}
alt={description}
style={{
width: '90px',
height: '90px',
borderRadius: '50%'
}}
/>
);
}
function Details({ username, position }) {
return (
<div style={{ marginTop: '15px' }}>
<h3 style={{ margin: 0 }}>{username}</h3>
<p style={{ color: '#7f8c8d', margin: '5px 0 0 0' }}>{position}</p>
</div>
);
}
ProfileCard.Picture = Picture;
ProfileCard.Details = Details;
export default ProfileCard;
Implementation in application:
// App.jsx
import ProfileCard from './components/ProfileCard';
function Application() {
return (
<div style={{ margin: '25px' }}>
<ProfileCard>
<ProfileCard.Picture
url="https://picsum.photos/id/237/200/200"
description="Profile Image"
/>
<ProfileCard.Details
username="Alex Johnson"
position="Senior Developer"
/>
</ProfileCard>
</div>
);
}
This pattern creates well-structured components that clearly express their relationships while maintaining clean import/export mechanics.