Welcome to Modern React Fundamentals! In this first lesson, you'll discover why React has become the dominant library for building user interfaces and how its component-based architecture revolutionizes web development. We'll explore React's core philosophy and set up the foundation for your journey into modern React development.
React is a JavaScript library for building user interfaces, particularly web applications with complex, interactive UIs. Created by Facebook (now Meta) in 2011, React has grown to become the most popular frontend library in the world.
React is built around a few key principles that make it powerful:
React's popularity isn't accidental. Here's why developers love it:
// A button component that can be used anywhere
function Button({ text, onClick }) {
return <button onClick={onClick}>{text}</button>
}
// Use it multiple times
<Button text="Click me" onClick={handleClick} />
<Button text="Submit" onClick={handleSubmit} />
React creates a virtual representation of the DOM and only updates what actually changes:
// React efficiently updates only the changed text
function Counter({ count }) {
return <h1>Count: {count}</h1>
}
Components are the heart of React. They're like JavaScript functions that return UI elements.
// A simple functional component
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>
}
// Using the component
function App() {
return <Welcome name="Sarah" />
}
Components can contain other components:
function Card({ children }) {
return (
<div className="card">
{children}
</div>
)
}
function UserProfile({ name, email }) {
return (
<Card>
<h2>{name}</h2>
<p>{email}</p>
</Card>
)
}
JSX lets you write HTML-like syntax directly in your JavaScript:
const element = <h1>Hello, world!</h1>
// It compiles to:
const element = React.createElement('h1', null, 'Hello, world!')
// ✅ Good
function App() {
return (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
)
}
// ✅ Also good (using Fragment)
function App() {
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
)
}
// ✅ Correct
<div className="container" onClick={handleClick} />
// ❌ Incorrect
<div class="container" onclick={handleClick} />
// ✅ Correct
<img src="image.jpg" alt="description" />
<br />
// ❌ Incorrect
<img src="image.jpg" alt="description">
<br>
Props (properties) let you pass data from parent to child components:
function Button({ variant, children, onClick }) {
const className = `btn btn-${variant}`
return (
<button className={className} onClick={onClick}>
{children}
</button>
)
}
function App() {
return (
<div>
<Button variant="primary" onClick={() => console.log('Primary clicked')}>
Primary Button
</Button>
<Button variant="secondary" onClick={() => console.log('Secondary clicked')}>
Secondary Button
</Button>
</div>
)
}
State is data that can change over time and trigger re-renders:
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<button onClick={() => setCount(count - 1)}>
Decrement
</button>
</div>
)
}
For modern React development, we recommend using Next.js:
npx create-next-app@latest my-react-app
cd my-react-app
npm run dev
my-react-app/
├── src/
│ ├── app/ # Next.js app router
│ ├── components/ # Reusable components
│ ├── lib/ # Utilities and helpers
│ └── styles/ # Global styles
├── public/ # Static assets
└── package.json
Let's create a simple interactive component:
// src/components/GreetingCard.jsx
import { useState } from 'react'
export default function GreetingCard() {
const [name, setName] = useState('')
const [submittedName, setSubmittedName] = useState('')
const handleSubmit = (e) => {
e.preventDefault()
setSubmittedName(name)
setName('')
}
return (
<div style={{
padding: '20px',
border: '1px solid #ccc',
borderRadius: '8px',
maxWidth: '300px'
}}>
{submittedName ? (
<h2>Hello, {submittedName}! 👋</h2>
) : (
<h2>Enter your name</h2>
)}
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Your name"
style={{
width: '100%',
padding: '8px',
margin: '10px 0',
border: '1px solid #ddd',
borderRadius: '4px'
}}
/>
<button
type="submit"
style={{
width: '100%',
padding: '10px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
Greet Me!
</button>
</form>
</div>
)
}
// ✅ Good
function UserProfileCard() { }
function NavigationMenu() { }
// ❌ Avoid
function card() { }
function nav() { }
components/
├── ui/
│ ├── Button/
│ │ ├── Button.jsx
│ │ └── index.js
│ └── Card/
└── features/
└── UserProfile/
Use TypeScript or PropTypes for type safety:
// With TypeScript
interface ButtonProps {
variant: 'primary' | 'secondary'
children: React.ReactNode
onClick?: () => void
}
function Button({ variant, children, onClick }: ButtonProps) {
// ...
}
function UserStatus({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<button>Logout</button>
) : (
<button>Login</button>
)}
</div>
)
}
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
</li>
))}
</ul>
)
}
function SearchBox() {
const [query, setQuery] = useState('')
const handleChange = (e) => {
setQuery(e.target.value)
}
const handleSearch = () => {
console.log('Searching for:', query)
}
return (
<div>
<input
type="text"
value={query}
onChange={handleChange}
placeholder="Search..."
/>
<button onClick={handleSearch}>Search</button>
</div>
)
}
In this lesson, you've learned:
Create a simple Temperature Converter component that:
Hint: The formula is: Fahrenheit = (Celsius × 9/5) + 32
In the next lesson, we'll dive deeper into Next.js and understand why it's the preferred framework for building production React applications. We'll explore its powerful features like server-side rendering, file-based routing, and built-in optimizations.
Ready to continue? Let's move on to understanding Next.js and how it enhances React development!