Component Architecture Implementation Patterns

1. React Functional Components Hooks

Hook Syntax Description Use Case
useState const [state, setState] = useState(initial) Manages component local state with immutable updates Form inputs, toggles, counters
useEffect useEffect(() => {}, [deps]) Handles side effects, subscriptions, data fetching API calls, DOM manipulation, subscriptions
useContext const value = useContext(Context) Consumes React context without wrapper components Theme, auth, global state access
useReducer const [state, dispatch] = useReducer(reducer, init) Complex state logic with predictable state transitions Form validation, multi-step wizards
useMemo const value = useMemo(() => compute(), [deps]) Memoizes expensive computations between renders Large list filtering, complex calculations
useCallback const fn = useCallback(() => {}, [deps]) Memoizes function references to prevent re-renders Event handlers in optimized children
useRef const ref = useRef(initialValue) Persists mutable value without triggering re-renders DOM access, storing previous values
useLayoutEffect useLayoutEffect(() => {}, [deps]) Synchronous effect before browser paint DOM measurements, animations

Example: Complete functional component with hooks

import { useState, useEffect, useCallback, useMemo } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchUser = async () => {
      setLoading(true);
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      setUser(data);
      setLoading(false);
    };
    fetchUser();
  }, [userId]);

  const handleUpdate = useCallback((updates) => {
    setUser(prev => ({ ...prev, ...updates }));
  }, []);

  const displayName = useMemo(() => 
    user ? `${user.firstName} ${user.lastName}` : 'Unknown',
    [user]
  );

  if (loading) return <div>Loading...</div>;

  return (
    <div>
      <h1>{displayName}</h1>
      <button onClick={() => handleUpdate({ active: true })}>
        Activate
      </button>
    </div>
  );
}

2. Vue 3 Composition API Setup

Function Syntax Description Use Case
ref const count = ref(0) Creates reactive primitive value with .value access Simple reactive state
reactive const state = reactive({}) Creates deeply reactive object proxy Complex nested state
computed const doubled = computed(() => count.value * 2) Cached derived state recalculated on dependency change Derived values, filters
watch watch(source, (newVal, oldVal) => {}) Performs side effects on reactive state changes API calls on input change
watchEffect watchEffect(() => console.log(count.value)) Automatically tracks dependencies and runs immediately Logging, analytics
onMounted onMounted(() => {}) Lifecycle hook after component DOM insertion Initialize third-party libraries
provide/inject provide('key', value); const val = inject('key') Dependency injection without prop drilling Plugin systems, themes

Example: Vue 3 Composition API component

<script setup>
import { ref, reactive, computed, watch, onMounted } from 'vue';

const count = ref(0);
const user = reactive({
  name: 'John',
  email: 'john@example.com'
});

const displayName = computed(() => 
  user.name.toUpperCase()
);

watch(count, (newCount, oldCount) => {
  console.log(`Count changed from ${oldCount} to ${newCount}`);
});

onMounted(() => {
  console.log('Component mounted');
});

const increment = () => count.value++;
</script>

<template>
  <div>
    <h1>{{ displayName }}</h1>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

3. Angular 17 Standalone Components NEW

Feature Syntax Description Use Case
@Component @Component({ standalone: true }) Self-contained component without NgModule Modern Angular architecture
imports imports: [CommonModule, FormsModule] Direct dependency declaration in component Explicit dependency management
Signal count = signal(0) Fine-grained reactive primitive for change detection Performance optimization
computed doubled = computed(() => count() * 2) Derived signal automatically updated Calculated values
effect effect(() => console.log(count())) Side effects triggered by signal changes Logging, analytics
Input/Output @Input() data; @Output() changed = new EventEmitter() Component communication interface Parent-child data flow

Example: Angular 17 standalone component with signals

import { Component, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-counter',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div>
      <h2>Counter: {{ count() }}</h2>
      <p>Doubled: {{ doubled() }}</p>
      <button (click)="increment()">Increment</button>
      <button (click)="decrement()">Decrement</button>
    </div>
  `
})
export class CounterComponent {
  count = signal(0);
  doubled = computed(() => this.count() * 2);

  increment() {
    this.count.update(n => n + 1);
  }

  decrement() {
    this.count.update(n => n - 1);
  }
}

4. Atomic Design System Storybook

Level Component Type Description Examples
Atoms Basic building blocks Smallest functional units, not divisible Button, Input, Label, Icon
Molecules Simple groups Combinations of atoms functioning together SearchBar, FormField, Card
Organisms Complex sections Complex UI sections with distinct functionality Header, Footer, ProductCard
Templates Page layouts Page-level structure without real content HomePageLayout, DashboardLayout
Pages Instances Templates with real content and data HomePage, UserProfilePage

Example: Storybook configuration and component story

// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  title: 'Atoms/Button',
  component: Button,
  tags: ['autodocs'],
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'danger']
    },
    size: {
      control: 'radio',
      options: ['sm', 'md', 'lg']
    }
  }
};

export default meta;
type Story = StoryObj<typeof Button>;

export const Primary: Story = {
  args: {
    variant: 'primary',
    children: 'Click Me',
    size: 'md'
  }
};

export const Secondary: Story = {
  args: {
    variant: 'secondary',
    children: 'Cancel',
    size: 'md'
  }
};

// SearchBar.stories.tsx (Molecule)
import { SearchBar } from './SearchBar';

export default {
  title: 'Molecules/SearchBar',
  component: SearchBar
};

export const Default = () => <SearchBar placeholder="Search..." />;
Note: Storybook v7+ uses CSF3 format with improved TypeScript support and automatic documentation generation.

5. Props Interface TypeScript Definitions

Pattern Syntax Description Use Case
Basic Interface interface Props { name: string } Type-safe prop definitions Component contracts
Optional Props title?: string Props that can be undefined Non-required attributes
Default Props name = 'Guest' Fallback values for props Default configurations
Union Types variant: 'primary' | 'secondary' Restricted string literal values Variant options
Generic Props interface Props<T> { data: T } Reusable type-safe components List, Table components
Children Prop children: React.ReactNode Type for child elements Container components
Event Handlers onClick: (e: MouseEvent) => void Type-safe event callbacks Interactive elements
Extending Props interface Props extends HTMLAttributes<T> Inherit native HTML props Wrapper components

Example: Comprehensive TypeScript component interfaces

// Basic Props Interface
interface ButtonProps {
  variant: 'primary' | 'secondary' | 'danger';
  size?: 'sm' | 'md' | 'lg';
  disabled?: boolean;
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  children: React.ReactNode;
}

function Button({ 
  variant, 
  size = 'md', 
  disabled = false, 
  onClick, 
  children 
}: ButtonProps) {
  return (
    <button 
      className={`btn btn-${variant} btn-${size}`}
      disabled={disabled}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

// Generic Props with Type Parameter
interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
  keyExtractor: (item: T) => string | number;
}

function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
  return (
    <ul>
      {items.map(item => (
        <li key={keyExtractor(item)}>
          {renderItem(item)}
        </li>
      ))}
    </ul>
  );
}

// Extending HTML Attributes
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
  label: string;
  error?: string;
}

function Input({ label, error, ...props }: InputProps) {
  return (
    <div>
      <label>{label}</label>
      <input {...props} />
      {error && <span className="error">{error}</span>}
    </div>
  );
}

6. Component Composition Higher-Order Components

Pattern Description Use Case Example
HOC Pattern Function that takes component, returns enhanced component Cross-cutting concerns, auth withAuth(Component)
Render Props Component shares code via function prop Dynamic rendering logic <Toggle render={(on) => ...} />
Compound Components Multiple components work together as single unit Flexible APIs like Select/Option <Select><Option/></Select>
Container/Presentational Separate data logic from UI rendering Reusable UI components UserContainer + UserView
Custom Hooks Reusable stateful logic extraction Shared behavior across components useAuth(), useFetch()

Example: HOC for authentication and loading states

// Higher-Order Component Pattern
function withAuth<P extends object>(
  Component: React.ComponentType<P>
) {
  return function AuthenticatedComponent(props: P) {
    const { user, loading } = useAuth();

    if (loading) return <div>Loading...</div>;
    if (!user) return <Navigate to="/login" />;

    return <Component {...props} user={user} />;
  };
}

// Usage
const ProtectedDashboard = withAuth(Dashboard);

// Render Props Pattern
function DataFetcher({ url, render }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(data => {
        setData(data);
        setLoading(false);
      });
  }, [url]);

  return render({ data, loading });
}

// Usage
<DataFetcher 
  url="/api/users" 
  render={({ data, loading }) => 
    loading ? <Spinner /> : <UserList users={data} />
  } 
/>

// Compound Components Pattern
const Select = ({ children, value, onChange }) => {
  return (
    <div className="select">
      {React.Children.map(children, child =>
        React.cloneElement(child, { selected: value, onSelect: onChange })
      )}
    </div>
  );
};

Select.Option = ({ value, selected, onSelect, children }) => (
  <div 
    className={selected === value ? 'selected' : ''}
    onClick={() => onSelect(value)}
  >
    {children}
  </div>
);

// Usage
<Select value={selected} onChange={setSelected}>
  <Select.Option value="1">Option 1</Select.Option>
  <Select.Option value="2">Option 2</Select.Option>
</Select>

Component Architecture Best Practices

  • Hooks preferred over class components in modern React for better composition
  • Use TypeScript interfaces for type-safe prop validation
  • Follow Atomic Design for consistent component hierarchy
  • Storybook essential for component development and documentation
  • Choose composition pattern based on reusability needs: HOC for cross-cutting, Render Props for dynamic logic, Compound for flexible APIs