Tags: React
, React Native
, Atomic Design
, Component Architecture
, Best Practices
Atomic Design offers a systematic approach to building maintainable UIs. Let's explore real-world implementations and professional patterns for React and React Native.
๏ฟฝ Modern Atomic Structure: Enhanced Folder Architecture
Scalable structure with TypeScript and cross-platform support:
src/
โโโ components/
โ โโโ atoms/
โ โ โโโ Button/
โ โ โ โโโ Button.tsx # Web implementation
โ โ โ โโโ Button.native.tsx # Mobile implementation
โ โ โ โโโ index.ts
โ โโโ molecules/
โ โโโ organisms/
โ
โโโ features/ # Optional feature-based grouping
โ โโโ cart/
โ โโโ CartItem.tsx # Feature-specific organism
โ
โโโ theme/
โ โโโ colors.ts
โ โโโ spacing.ts
Key improvement: Platform-specific files and feature-based grouping when needed.
๐งช Real-World Component Examples
This section showcases practical implementations of atomic design principles in React and React Native.
1. Smart Image Atom (Cross-Platform)
// components/atoms/Image/Image.tsx (Web)
import { useState } from "react";
type ImageProps = {
src: string;
fallback?: string;
alt: string;
className?: string;
};
export const Image = ({ src, fallback, alt, className }: ImageProps) => {
const [source, setSource] = useState(src);
const handleError = () => {
if (fallback) setSource(fallback);
};
return (
<img
src={source}
alt={alt}
className={className}
onError={handleError}
loading="lazy"
/>
);
};
// components/atoms/Image/Image.native.tsx (Mobile)
import { Image as RNImage } from "react-native";
export const Image = ({ src, fallback, style }) => (
<RNImage
source={{ uri: src }}
defaultSource={fallback}
style={style}
accessibilityRole="image"
/>
);
Features:
- Lazy loading (web)
- Error fallback
- Accessibility roles
- Platform-specific optimizations
2. Form Field Molecule with Validation
// components/molecules/FormField/FormField.tsx
import { useState, useEffect } from "react";
import { TextInput, Label, ErrorText } from "../atoms";
type FormFieldProps = {
label: string;
type?: "text" | "email" | "password";
required?: boolean;
validator?: (value: string) => string | null;
};
export const FormField = ({
label,
type = "text",
validator,
}: FormFieldProps) => {
const [value, setValue] = useState("");
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (validator && value) {
setError(validator(value));
}
}, [value, validator]);
return (
<div className="form-field">
<Label htmlFor={label}>{label}</Label>
<TextInput
id={label}
type={type}
value={value}
onChange={(e) => setValue(e.target.value)}
aria-invalid={!!error}
/>
{error && <ErrorText>{error}</ErrorText>}
</div>
);
};
Features:
- Validation system
- Accessibility labels
- Reusable across forms
- Type safety with TypeScript
3. Product Card Organism
// components/organisms/ProductCard/ProductCard.tsx
import { Image, Button, PriceDisplay } from "../../atoms";
type Product = {
id: string;
name: string;
price: number;
imageUrl: string;
};
export const ProductCard = ({ product }: { product: Product }) => (
<article className="product-card">
<Image
src={product.imageUrl}
fallback="/product-fallback.jpg"
alt={product.name}
/>
<h3>{product.name}</h3>
<PriceDisplay value={product.price} currency="USD" />
<Button
variant="primary"
onClick={() => addToCart(product.id)}
aria-label={`Add ${product.name} to cart`}
>
Add to Cart
</Button>
</article>
);
Features:
- Composite UI with multiple atoms
- Type-safe product interface
- Accessibility labels
- Consistent styling system
๐ Advanced Patterns & Best Practices
1. State Management Boundaries
// Good practice - Keep atoms stateless
const Counter = ({ count, onIncrement }) => (
<div>
<span>{count}</span>
<Button onClick={onIncrement}>+</Button>
</div>
);
// Bad practice - Avoid state in atoms
const Counter = () => {
const [count, setCount] = useState(0);
return (...);
};
2. Performance Optimization
// Memoize expensive components
import { memo } from "react";
const HeavyList = memo(({ items }) => (
<ul>
{items.map((item) => (
<ListItem key={item.id} {...item} />
))}
</ul>
));
3. Cross-Platform Strategy
// components/atoms/Button/index.ts
export { default as Button } from "./Button";
// Automatically imports .native.tsx for React Native
// Shared props interface
interface ButtonProps {
variant?: "primary" | "secondary";
accessibilityLabel?: string;
onPress: () => void;
}
4. Accessibility First
// components/atoms/IconButton.tsx
export const IconButton = ({ icon, label, ...props }) => (
<button {...props} aria-label={label} className="icon-button">
<Icon name={icon} />
</button>
);
5. Theme Provider Pattern
// theme/ThemeProvider.tsx
import { ThemeProvider as StyledProvider } from "styled-components";
const theme = {
colors: {
primary: "#2196F3",
error: "#FF5252",
},
spacing: (multiplier: number) => `${4 * multiplier}px`,
};
export const ThemeProvider = ({ children }) => (
<StyledProvider theme={theme}>{children}</StyledProvider>
);
๐ฑ React Native Specific Patterns
1. Safe Area Handling
// templates/MainLayout.native.tsx
import { SafeAreaView } from "react-native";
export const MainLayout = ({ children }) => (
<SafeAreaView style={styles.container}>
<Header />
{children}
</SafeAreaView>
);
2. Touch Interaction Best Practice
// molecules/ListItem.native.tsx
import { Pressable, View } from "react-native";
export const ListItem = ({ title, onPress }) => (
<Pressable
onPress={onPress}
android_ripple={{ color: "#ddd" }}
style={({ pressed }) => [styles.item, pressed && styles.pressed]}
>
<Text>{title}</Text>
</Pressable>
);
๐ง Architectural Insights
- Cross-Platform Metrics
// theme/spacing.ts
export const spacing = {
base: 8,
get vertical() {
return Platform.select({
web: this.base * 2,
default: this.base,
});
},
};
- Feature-Sliced Structure
features/
authentication/
components/
LoginForm.tsx
hooks/
useAuth.ts
- Documentation Strategy
/**
* @component FormField
* @description Reusable form input with validation
* @prop {string} label - Input label
* @prop {function} validator - Validation function
* @example
* <FormField
* label="Email"
* validator={(v) => isValidEmail(v) ? null : 'Invalid email'}
* />
*/
๐ Conclusion
By implementing these real-world patterns:
โ
Achieve true cross-platform consistency
โ
Build maintainable component systems
โ
Enhance team collaboration
โ
Improve testability
โ
Future-proof your architecture
Atomic Design is not just a patternโit's a mindset that helps teams scale their UIs in a systematic and consistent way. Whether you're building for web or mobile, applying this approach in React and React Native can dramatically improve your component architecture.
Top comments (1)
insane depth here, i honestly wish i had this when i started building my first real project