1.
Build a Counter App with Increment, Decrement,
and Reset
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div style={{ textAlign: 'center' }}>
<h2>Count: {count}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count > 0 ? count - 1 : 0)}>Decrement</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
};
export default Counter;
2. To-Do List with Add, Delete, and Toggle Completion
import React, { useState } from 'react';
const TodoApp = () => {
const [task, setTask] = useState('');
const [todos, setTodos] = useState([]);
const addTask = () => {
if (task.trim()) {
setTodos([...todos, { id: Date.now(), text: task, done: false }]);
setTask('');
};
const toggleTask = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, done: !todo.done } : todo
));
};
const deleteTask = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
return (
<div>
<h2>Todo List</h2>
<input value={task} onChange={(e) => setTask(e.target.value)} />
<button onClick={addTask}>Add</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<span
onClick={() => toggleTask(todo.id)}
style={{ textDecoration: todo.done ? 'line-through' : 'none', cursor: 'pointer' }}
>
{todo.text}
</span>
<button onClick={() => deleteTask(todo.id)}> </button>
</li>
))}
</ul>
</div>
);
};
3. Search Filter List
export default TodoApp;
import React, { useState } from 'react';
const users = ['Alice', 'Bob', 'Charlie', 'David', 'Eva'];
const SearchFilter = () => {
const [search, setSearch] = useState('');
const filteredUsers = users.filter(user =>
user.toLowerCase().includes(search.toLowerCase())
);
return (
<div>
<input
placeholder="Search user..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<ul>
{filteredUsers.map((user, idx) => (
<li key={idx}>{user}</li>
))}
</ul>
</div>
);
};
export default SearchFilter;
4. Accordion Component (Expandable/Collapsible
Sections)
import React, { useState } from 'react';
const data = [
{ title: 'Section 1', content: 'This is section 1 content' },
{ title: 'Section 2', content: 'This is section 2 content' },
{ title: 'Section 3', content: 'This is section 3 content' },
];
const Accordion = () => {
const [openIndex, setOpenIndex] = useState(null);
return (
<div>
{data.map((item, idx) => (
<div key={idx}>
<h3 onClick={() => setOpenIndex(openIndex === idx ? null : idx)}>
{item.title}
</h3>
{openIndex === idx && <p>{item.content}</p>}
</div>
))}
</div>
);
};
export default Accordion;
5. Debounce Search Input
import React, { useState, useEffect } from 'react';
const DebounceSearch = () => {
const [input, setInput] = useState('');
const [debounced, setDebounced] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setDebounced(input);
console.log('Searching for:', input);
}, 500);
return () => clearTimeout(timer);
}, [input]);
return (
<div>
<input
placeholder="Search..."
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<p>Search result for: {debounced}</p>
</div>
);
};
export default DebounceSearch;
6. Form Validation with Error Messages
import React, { useState } from 'react';
const FormValidation = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState({});
const validate = () => {
const errs = {};
if (!email.includes('@')) errs.email = 'Invalid email';
if (password.length < 6) errs.password = 'Min 6 characters';
setErrors(errs);
return Object.keys(errs).length === 0;
};
const handleSubmit = (e) => {
e.preventDefault();
if (validate()) {
alert('Form submitted');
};
return (
<form onSubmit={handleSubmit}>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
/>
<div style={{ color: 'red' }}>{errors.email}</div>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<div style={{ color: 'red' }}>{errors.password}</div>
<button type="submit" disabled={!email || !password}>
Submit
</button>
</form>
);
};
export default FormValidation;
8. Tabs Component
import React, { useState } from 'react';
const tabs = [
{ label: 'Home', content: 'This is the home tab' },
{ label: 'About', content: 'This is the about tab' },
{ label: 'Contact', content: 'This is the contact tab' },
];
const Tabs = () => {
const [active, setActive] = useState(0);
return (
<div>
<div style={{ display: 'flex' }}>
{tabs.map((tab, index) => (
<button
key={index}
onClick={() => setActive(index)}
style={{
fontWeight: active === index ? 'bold' : 'normal',
marginRight: 10,
}}
>
{tab.label}
</button>
))}
</div>
<div style={{ marginTop: 20 }}>
<p>{tabs[active].content}</p>
</div>
</div>
);
};
export default Tabs;
10. Pagination Component
import React, { useState } from 'react';
const data = Array.from({ length: 50 }, (_, i) => `Item ${i + 1}`);
const Pagination = () => {
const [page, setPage] = useState(1);
const perPage = 10;
const start = (page - 1) * perPage;
const end = start + perPage;
const totalPages = Math.ceil(data.length / perPage);
return (
<div>
<ul>
{data.slice(start, end).map((item, idx) => (
<li key={idx}>{item}</li>
))}
</ul>
<div>
<button disabled={page === 1} onClick={() => setPage(p => p - 1)}>Prev</button>
<span> Page {page} of {totalPages} </span>
<button disabled={page === totalPages} onClick={() => setPage(p => p + 1)}>Next</button>
</div>
</div>
);
};
export default Pagination;