React: Getting Started and JSX
React is a powerful library for building user interfaces. This article covers JSX, components, props, and fundamental React concepts.
Introduction
React provides:
- Component-based architecture
- Declarative UI
- Reusable components
- Efficient rendering
- Developer experience
Understanding React helps you:
- Build interactive UIs
- Create reusable components
- Manage application state
- Build scalable applications
- Improve development productivity
Setting Up React
Create React App
# โ
Good: Create React app
npx create-react-app my-app
cd my-app
npm start
# โ
Good: With TypeScript
npx create-react-app my-app --template typescript
# โ
Good: Vite (faster alternative)
npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev
Project Structure
my-app/
โโโ src/
โ โโโ components/
โ โ โโโ Header.jsx
โ โ โโโ Footer.jsx
โ โ โโโ Button.jsx
โ โโโ pages/
โ โ โโโ Home.jsx
โ โ โโโ About.jsx
โ โโโ App.jsx
โ โโโ index.css
โ โโโ main.jsx
โโโ public/
โโโ package.json
โโโ vite.config.js
JSX Basics
Understanding JSX
// โ
Good: JSX syntax
const element = <h1>Hello, React!</h1>;
// โ
Good: JSX with expressions
const name = 'John';
const greeting = <h1>Hello, {name}!</h1>;
// โ
Good: JSX with attributes
const image = <img src="logo.png" alt="Logo" />;
// โ
Good: JSX with children
const card = (
<div className="card">
<h2>Title</h2>
<p>Content</p>
</div>
);
// โ
Good: JSX with conditional rendering
const isLoggedIn = true;
const ui = isLoggedIn ? <h1>Welcome!</h1> : <h1>Please log in</h1>;
JSX Rules
// โ
Good: Single root element
const element = (
<div>
<h1>Title</h1>
<p>Content</p>
</div>
);
// โ Bad: Multiple root elements
// const element = (
// <h1>Title</h1>
// <p>Content</p>
// );
// โ
Good: Close all tags
const element = <img src="logo.png" />;
// โ
Good: Use className instead of class
const element = <div className="container">Content</div>;
// โ
Good: Use camelCase for attributes
const element = <input onChange={handleChange} />;
Components
Functional Components
// โ
Good: Functional component
function Welcome() {
return <h1>Hello, React!</h1>;
}
// โ
Good: Arrow function component
const Welcome = () => {
return <h1>Hello, React!</h1>;
};
// โ
Good: Component with JSX
const Card = () => {
return (
<div className="card">
<h2>Card Title</h2>
<p>Card content</p>
</div>
);
};
// โ
Good: Export component
export default Welcome;
Using Components
// โ
Good: Use component
function App() {
return (
<div>
<Welcome />
<Card />
</div>
);
}
// โ
Good: Component composition
function Dashboard() {
return (
<div>
<Header />
<MainContent />
<Footer />
</div>
);
}
Props
Passing Props
// โ
Good: Component with props
function Greeting({ name, age }) {
return (
<div>
<h1>Hello, {name}!</h1>
<p>You are {age} years old</p>
</div>
);
}
// โ
Good: Using component with props
function App() {
return <Greeting name="John" age={30} />;
}
// โ
Good: Default props
function Button({ label = 'Click me', onClick }) {
return <button onClick={onClick}>{label}</button>;
}
// โ
Good: Props with children
function Card({ title, children }) {
return (
<div className="card">
<h2>{title}</h2>
<div>{children}</div>
</div>
);
}
// Usage
<Card title="My Card">
<p>Card content</p>
</Card>
Props Validation
// โ
Good: PropTypes validation
import PropTypes from 'prop-types';
function User({ name, age, email }) {
return (
<div>
<h1>{name}</h1>
<p>Age: {age}</p>
<p>Email: {email}</p>
</div>
);
}
User.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
email: PropTypes.string.isRequired
};
// โ
Good: TypeScript types
interface UserProps {
name: string;
age?: number;
email: string;
}
function User({ name, age, email }: UserProps) {
return (
<div>
<h1>{name}</h1>
<p>Age: {age}</p>
<p>Email: {email}</p>
</div>
);
}
State
Using State
import { useState } from 'react';
// โ
Good: useState hook
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
// โ
Good: Multiple state variables
function Form() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
return (
<form>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
</form>
);
}
// โ
Good: State with objects
function User() {
const [user, setUser] = useState({
name: 'John',
age: 30,
email: '[email protected]'
});
const updateName = (newName) => {
setUser({ ...user, name: newName });
};
return (
<div>
<h1>{user.name}</h1>
<button onClick={() => updateName('Jane')}>
Change Name
</button>
</div>
);
}
Events
Handling Events
// โ
Good: Event handlers
function Button() {
const handleClick = () => {
console.log('Button clicked');
};
return <button onClick={handleClick}>Click me</button>;
}
// โ
Good: Event with parameters
function List() {
const handleItemClick = (id) => {
console.log(`Item ${id} clicked`);
};
return (
<ul>
<li onClick={() => handleItemClick(1)}>Item 1</li>
<li onClick={() => handleItemClick(2)}>Item 2</li>
</ul>
);
}
// โ
Good: Form events
function Form() {
const handleSubmit = (e) => {
e.preventDefault();
console.log('Form submitted');
};
return (
<form onSubmit={handleSubmit}>
<input type="text" />
<button type="submit">Submit</button>
</form>
);
}
// โ
Good: Input events
function Input() {
const [value, setValue] = useState('');
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
onFocus={() => console.log('Focused')}
onBlur={() => console.log('Blurred')}
/>
);
}
Practical Examples
Todo App
import { useState } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
const addTodo = () => {
if (input.trim()) {
setTodos([...todos, { id: Date.now(), text: input }]);
setInput('');
}
};
const removeTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
return (
<div>
<h1>Todo App</h1>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Add a todo"
/>
<button onClick={addTodo}>Add</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => removeTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default TodoApp;
User Profile
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const fetchUser = async () => {
try {
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUser(data);
} catch (error) {
console.error('Error fetching user:', error);
} finally {
setLoading(false);
}
};
if (loading) return <p>Loading...</p>;
if (!user) return <p>User not found</p>;
return (
<div>
<h1>{user.name}</h1>
<p>Email: {user.email}</p>
<p>Age: {user.age}</p>
</div>
);
}
export default UserProfile;
Best Practices
-
Use functional components:
// โ Good function Welcome() { return <h1>Hello</h1>; } // โ Bad (class components are outdated) class Welcome extends React.Component { render() { return <h1>Hello</h1>; } } -
Keep components small:
// โ Good function Button({ label, onClick }) { return <button onClick={onClick}>{label}</button>; } // โ Bad (too much logic) function ComplexComponent() { // 500 lines of code } -
Use keys in lists:
// โ Good {items.map(item => <Item key={item.id} {...item} />)} // โ Bad {items.map((item, index) => <Item key={index} {...item} />)}
Common Mistakes
-
Mutating state directly:
// โ Bad state.name = 'John'; // โ Good setState({ ...state, name: 'John' }); -
Missing keys in lists:
// โ Bad {items.map(item => <Item {...item} />)} // โ Good {items.map(item => <Item key={item.id} {...item} />)}
Summary
React fundamentals are essential. Key takeaways:
- Understand JSX syntax
- Create functional components
- Use props for data passing
- Manage state with hooks
- Handle events properly
- Keep components small
- Use keys in lists
- Follow best practices
Related Resources
Next Steps
- Learn about React Hooks
- Explore React Component Patterns
- Study State Management
- Practice React components
- Build React applications
Comments