React Architecture and Modern Development Setup
60 minReact is a declarative, efficient, and flexible JavaScript library for building user interfaces. Created by Facebook in 2013, it has become the foundation for modern web development with its component-based architecture.
Modern React development requires a comprehensive toolchain including build tools (Vite, Webpack), package managers (npm/yarn), linting (ESLint), formatting (Prettier), and testing frameworks (Jest, React Testing Library).
JSX is a syntax extension that allows you to write HTML-like code in JavaScript. It gets transformed into React.createElement() calls during compilation, enabling powerful component composition and dynamic rendering.
Understanding React's virtual DOM, reconciliation process, and unidirectional data flow is crucial for building performant applications and debugging effectively.
Key Concepts
- React uses a component-based architecture for building reusable UI elements.
- JSX syntax allows writing HTML-like code that compiles to JavaScript.
- The virtual DOM enables efficient updates by minimizing direct DOM manipulation.
- React follows a unidirectional data flow pattern for predictable state management.
- Modern tooling (Vite, ESLint, Prettier) enhances development productivity.
Learning Objectives
Master
- Setting up a modern React development environment with Vite
- Understanding the relationship between JSX and React.createElement
- Configuring ESLint and Prettier for code quality
- Organizing project structure for scalability
Develop
- Component-based thinking and architecture design
- Modern development workflow efficiency
- Understanding of build tools and their configuration
Tips
- Use Vite over Create React App for faster development and smaller bundles.
- Configure ESLint rules early to catch errors during development.
- Set up Prettier with ESLint integration for consistent code formatting.
- Use React Developer Tools browser extension for debugging components.
Common Pitfalls
- Mixing class components with functional components unnecessarily.
- Not using React.StrictMode during development to catch potential issues.
- Forgetting to configure path aliases in build tools for cleaner imports.
- Overlooking the importance of proper project structure from the start.
Summary
- React is a component-based library for building user interfaces.
- Modern tooling (Vite, ESLint, Prettier) is essential for professional development.
- JSX compiles to React.createElement() calls.
- Understanding the virtual DOM is key to React's performance.
Exercise
Set up a complete React development environment with modern tooling, create a component library structure, and implement best practices for project organization.
// Modern React Project Setup
// package.json
{
"name": "modern-react-app",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint src --ext js,jsx,ts,tsx",
"lint:fix": "eslint src --ext js,jsx,ts,tsx --fix",
"format": "prettier --write src/**/*.{js,jsx,ts,tsx,css,md}",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.8.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@vitejs/plugin-react": "^3.1.0",
"eslint": "^8.36.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"jest": "^29.5.0",
"@testing-library/react": "^13.4.0",
"@testing-library/jest-dom": "^5.16.5",
"prettier": "^2.8.7",
"vite": "^4.1.4"
}
}
// src/main.jsx - Application entry point
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { App } from './App';
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
// src/App.jsx - Main application component
import React, { Suspense, lazy } from 'react';
import { Routes, Route } from 'react-router-dom';
import { ErrorBoundary } from './components/ErrorBoundary';
import { LoadingSpinner } from './components/LoadingSpinner';
import { Header } from './components/Header';
import { Footer } from './components/Footer';
import './App.css';
// Lazy load components for code splitting
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Contact = lazy(() => import('./pages/Contact'));
export function App() {
return (
<ErrorBoundary>
<div className="app">
<Header />
<main className="main-content">
<Suspense fallback={<LoadingSpinner />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</main>
<Footer />
</div>
</ErrorBoundary>
);
}
// src/components/ErrorBoundary.jsx - Error handling
import React from 'react';
export class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
this.setState({
error: error,
errorInfo: errorInfo
});
// Log error to monitoring service in production
console.error('Error caught by boundary:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return (
<div className="error-boundary">
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
<br />
{this.state.errorInfo.componentStack}
</details>
</div>
);
}
return this.props.children;
}
}
// src/components/LoadingSpinner.jsx - Loading component
import React from 'react';
import './LoadingSpinner.css';
export function LoadingSpinner() {
return (
<div className="loading-spinner">
<div className="spinner"></div>
<p>Loading...</p>
</div>
);
}
// src/components/Header.jsx - Navigation component
import React from 'react';
import { Link, useLocation } from 'react-router-dom';
import './Header.css';
export function Header() {
const location = useLocation();
const isActive = (path) => location.pathname === path;
return (
<header className="header">
<nav className="nav">
<Link to="/" className="nav-brand">
Modern React App
</Link>
<ul className="nav-links">
<li>
<Link
to="/"
className={isActive('/') ? 'nav-link active' : 'nav-link'}
>
Home
</Link>
</li>
<li>
<Link
to="/about"
className={isActive('/about') ? 'nav-link active' : 'nav-link'}
>
About
</Link>
</li>
<li>
<Link
to="/contact"
className={isActive('/contact') ? 'nav-link active' : 'nav-link'}
>
Contact
</Link>
</li>
</ul>
</nav>
</header>
);
}
// src/pages/Home.jsx - Home page component
import React from 'react';
import { WelcomeSection } from '../components/WelcomeSection';
import { FeatureGrid } from '../components/FeatureGrid';
import './Home.css';
export function Home() {
return (
<div className="home">
<WelcomeSection />
<FeatureGrid />
</div>
);
}
// src/components/WelcomeSection.jsx - Welcome component
import React from 'react';
import './WelcomeSection.css';
export function WelcomeSection() {
return (
<section className="welcome-section">
<div className="container">
<h1>Welcome to Modern React Development</h1>
<p>
This is a comprehensive example of modern React development practices,
including proper project structure, error boundaries, lazy loading,
and component composition.
</p>
<div className="welcome-features">
<div className="feature">
<h3>๐ Performance</h3>
<p>Optimized with code splitting and lazy loading</p>
</div>
<div className="feature">
<h3>๐ก๏ธ Reliability</h3>
<p>Error boundaries for graceful error handling</p>
</div>
<div className="feature">
<h3>๐ฑ Responsive</h3>
<p>Mobile-first design with modern CSS</p>
</div>
</div>
</div>
</section>
);
}
// src/components/FeatureGrid.jsx - Feature showcase
import React from 'react';
import './FeatureGrid.css';
const features = [
{
id: 1,
title: 'Component Architecture',
description: 'Reusable, composable components',
icon: '๐งฉ'
},
{
id: 2,
title: 'State Management',
description: 'Efficient state handling with hooks',
icon: 'โก'
},
{
id: 3,
title: 'Routing',
description: 'Client-side routing with React Router',
icon: '๐ฃ๏ธ'
},
{
id: 4,
title: 'Testing',
description: 'Comprehensive testing with Jest and RTL',
icon: '๐งช'
}
];
export function FeatureGrid() {
return (
<section className="feature-grid">
<div className="container">
<h2>Key Features</h2>
<div className="grid">
{features.map(feature => (
<div key={feature.id} className="feature-card">
<div className="feature-icon">{feature.icon}</div>
<h3>{feature.title}</h3>
<p>{feature.description}</p>
</div>
))}
</div>
</div>
</section>
);
}
// src/index.css - Global styles
:root {
--primary-color: #007bff;
--secondary-color: #6c757d;
--success-color: #28a745;
--danger-color: #dc3545;
--warning-color: #ffc107;
--info-color: #17a2b8;
--light-color: #f8f9fa;
--dark-color: #343a40;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 1.6;
color: var(--dark-color);
}
.app {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.main-content {
flex: 1;
padding: 2rem 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
/* Responsive design */
@media (max-width: 768px) {
.container {
padding: 0 0.5rem;
}
}
Exercise Tips
- Start with 'npm create vite@latest' for the fastest setup.
- Install ESLint and Prettier as dev dependencies.
- Create a 'src/components' folder structure early.
- Configure path aliases in vite.config.js for '@/' imports.