8 React Projects for Building Your Skills
Building React projects is a great way to improve your skills and gain practical experience. Here are ten project ideas that vary in complexity, allowing you to enhance your React proficiency gradually:
To-Do List app
Create a simple to-do list where users can add, edit, and mark tasks as completed. You can also add features like filtering, sorting, and storing tasks in local storage.
import React, { useState } from 'react';
const TodoApp = () => {
const [tasks, setTasks] = useState([]);
const [task, setTask] = useState('');
const handleInputChange = (e) => {
setTask(e.target.value);
};
const handleAddTask = () => {
if (task.trim() !== '') {
setTasks([...tasks, { text: task, completed: false }]);
setTask('');
}
};
const handleToggleComplete = (index) => {
const updatedTasks = tasks.map((t, i) =>
i === index ? { ...t, completed: !t.completed } : t
);
setTasks(updatedTasks);
};
const handleRemoveTask = (index) => {
const updatedTasks = tasks.filter((t, i) => i !== index);
setTasks(updatedTasks);
};
return (
<div>
<h1>To-Do List</h1>
<div>
<input
type="text"
value={task}
onChange={handleInputChange}
placeholder="Add a task..."
/>
<button onClick={handleAddTask}>Add</button>
</div>
<ul>
{tasks.map((t, index) => (
<li key={index}>
<input
type="checkbox"
checked={t.completed}
onChange={() => handleToggleComplete(index)}
/>
<span style={{ textDecoration: t.completed ? 'line-through' : 'none' }}>{t.text}</span>
<button onClick={() => handleRemoveTask(index)}>Remove</button>
</li>
))}
</ul>
</div>
);
};
export default TodoApp;
To use this code, you'll need to set up a React project and create a component file (e.g., TodoApp.js
) where you can paste this code. Then, you can import and use the TodoApp
component in your main application file.
This code sets up a functional component TodoApp
that maintains an array of tasks in its state using the useState
hook. It provides input fields to add tasks, checkboxes to mark tasks as completed, and buttons to remove tasks.
Keep in mind that this is a basic example, and you can extend and customize it further based on your specific requirements.
Weather App
Build a weather application that fetches data from a weather API and displays the current weather conditions and forecasts for a specific location.
import React, { useState } from 'react';
const WeatherApp = () => {
const [city, setCity] = useState('');
const [weatherData, setWeatherData] = useState(null);
const apiKey = 'YOUR_API_KEY'; // Replace with your own API key
const fetchWeatherData = async () => {
try {
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${apiKey}`
);
if (!response.ok) {
throw new Error('City not found');
}
const data = await response.json();
setWeatherData(data);
} catch (error) {
alert(error.message);
}
};
const handleInputChange = (e) => {
setCity(e.target.value);
};
const handleSearch = () => {
fetchWeatherData();
};
return (
<div>
<h1>Weather App</h1>
<div>
<input
type="text"
value={city}
onChange={handleInputChange}
placeholder="Enter city name"
/>
<button onClick={handleSearch}>Search</button>
</div>
{weatherData && (
<div>
<h2>{weatherData.name}</h2>
<p>{weatherData.weather[0].description}</p>
<p>Temperature: {weatherData.main.temp}°C</p>
<p>Humidity: {weatherData.main.humidity}%</p>
</div>
)}
</div>
);
};
export default WeatherApp;
Here's how the code works:
- We use the
useState
hook to manage the city input and the weather data. - The
fetchWeatherData
function makes an API call to OpenWeatherMap to get weather data based on the provided city. - The
handleInputChange
function updates thecity
state as the user types in the input field. - When the user clicks the "Search" button, it triggers the
handleSearch
function which callsfetchWeatherData
. - If the API call is successful, the weather data is stored in the
weatherData
state. - The component renders the input field, search button, and displays the weather information if available.
Remember to replace 'YOUR_API_KEY'
with your actual API key from OpenWeatherMap. You can sign up on their website to get a free API key.
To use this code, you'll need to set up a React project and create a component file (e.g., WeatherApp.js
) where you can paste this code. Then, you can import and use the WeatherApp
component in your main application file.
Expense Tracker
Develop an application to track income and expenses. Allow users to add, edit, and delete transactions and display a summary of their financial activities.
Below is an example of a simple expense tracker app using React. This app allows users to add, edit, and delete transactions, and it displays a summary of their financial activities.
import React, { useState } from 'react';
const ExpenseTracker = () => {
const [transactions, setTransactions] = useState([]);
const [text, setText] = useState('');
const [amount, setAmount] = useState('');
const addTransaction = () => {
if (text.trim() !== '' && !isNaN(Number(amount))) {
const newTransaction = {
id: Math.random(),
text: text,
amount: +amount
};
setTransactions([...transactions, newTransaction]);
setText('');
setAmount('');
}
};
const deleteTransaction = (id) => {
const updatedTransactions = transactions.filter((transaction) => transaction.id !== id);
setTransactions(updatedTransactions);
};
const totalIncome = transactions.reduce((acc, transaction) => {
return transaction.amount > 0 ? acc + transaction.amount : acc;
}, 0);
const totalExpense = transactions.reduce((acc, transaction) => {
return transaction.amount < 0 ? acc + transaction.amount : acc;
}, 0);
return (
<div>
<h1>Expense Tracker</h1>
<div>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Enter description"
/>
<input
type="number"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Enter amount"
/>
<button onClick={addTransaction}>Add Transaction</button>
</div>
<div>
<h2>Transactions</h2>
<ul>
{transactions.map((transaction) => (
<li key={transaction.id}>
{transaction.text} - {transaction.amount}{' '}
<button onClick={() => deleteTransaction(transaction.id)}>Delete</button>
</li>
))}
</ul>
</div>
<div>
<h2>Summary</h2>
<p>Total Income: {totalIncome}</p>
<p>Total Expense: {totalExpense}</p>
<p>Balance: {totalIncome + totalExpense}</p>
</div>
</div>
);
};
export default ExpenseTracker;
In this example:
- We use the
useState
hook to manage the state of transactions, text input, and amount input. - The
addTransaction
function adds a new transaction to the list if both the description (text
) and amount are valid. - The
deleteTransaction
function filters out the transaction with the specified ID to remove it from the list. - The
totalIncome
andtotalExpense
variables calculate the sums of income and expenses, respectively. - The component renders input fields for description and amount, a button to add a transaction, a list of transactions, and a summary section.
You can create a new component file (e.g., ExpenseTracker.js
) in your React project, paste this code, and then import and use the ExpenseTracker
component in your main application file.
Feel free to modify and extend this code to suit your specific requirements!
E-commerce Storefront
Design a basic e-commerce site with features like product listings, search, product details, and a shopping cart. You can also implement user authentication and a checkout process.
Creating a full-fledged e-commerce storefront involves a lot of components and features, so I'll provide a simplified example to get you started. This example will include product listings, a shopping cart, and basic functionality to add and remove items.
import React, { useState } from 'react';
const Product = ({ product, onAddToCart }) => {
return (
<div className="product">
<h3>{product.name}</h3>
<p>Price: ${product.price}</p>
<button onClick={() => onAddToCart(product)}>Add to Cart</button>
</div>
);
};
const CartItem = ({ item, onRemoveFromCart }) => {
return (
<div className="cart-item">
<span>{item.name}</span>
<span>Quantity: {item.quantity}</span>
<button onClick={() => onRemoveFromCart(item)}>Remove</button>
</div>
);
};
const EcommerceStorefront = () => {
const [products] = useState([
{ id: 1, name: 'Product A', price: 10 },
{ id: 2, name: 'Product B', price: 20 },
{ id: 3, name: 'Product C', price: 30 },
]);
const [cart, setCart] = useState([]);
const handleAddToCart = (product) => {
const existingItem = cart.find((item) => item.id === product.id);
if (existingItem) {
const updatedCart = cart.map((item) =>
item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item
);
setCart(updatedCart);
} else {
setCart([...cart, { ...product, quantity: 1 }]);
}
};
const handleRemoveFromCart = (item) => {
const updatedCart = cart.filter((cartItem) => cartItem.id !== item.id);
setCart(updatedCart);
};
return (
<div>
<h1>E-commerce Storefront</h1>
<div className="products">
{products.map((product) => (
<Product key={product.id} product={product} onAddToCart={handleAddToCart} />
))}
</div>
<div className="cart">
<h2>Shopping Cart</h2>
{cart.map((item) => (
<CartItem key={item.id} item={item} onRemoveFromCart={handleRemoveFromCart} />
))}
</div>
</div>
);
};
export default EcommerceStorefront;
In this example:
- We have a
Product
component that displays the name, price, and an "Add to Cart" button for a given product. - We also have a
CartItem
component that displays the name, quantity, and a "Remove" button for an item in the shopping cart. - The
EcommerceStorefront
component manages the list of products and the shopping cart using theuseState
hook. - The
handleAddToCart
function adds items to the cart, updating the quantity if the item already exists. - The
handleRemoveFromCart
function removes items from the cart.
Please note that this is a simplified example and doesn't include features like authentication, actual product images, payment processing, or routing. In a real-world application, you would need to implement these and other features to create a complete e-commerce storefront.
Blog Platform
Create a blogging platform where users can register, create, edit, and delete posts. Implement features like user authentication and authorization.
Creating a full-fledged blog platform is a complex task that involves many components and features. I'll provide a simplified example to get you started. This example will include basic functionality to create, edit, and delete blog posts.
import React, { useState } from 'react';
const BlogPost = ({ post, onDelete }) => {
return (
<div className="blog-post">
<h2>{post.title}</h2>
<p>{post.content}</p>
<button onClick={() => onDelete(post.id)}>Delete</button>
</div>
);
};
const BlogPlatform = () => {
const [posts, setPosts] = useState([]);
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const addPost = () => {
if (title.trim() !== '' && content.trim() !== '') {
const newPost = {
id: Date.now(),
title: title,
content: content
};
setPosts([...posts, newPost]);
setTitle('');
setContent('');
}
};
const deletePost = (id) => {
const updatedPosts = posts.filter((post) => post.id !== id);
setPosts(updatedPosts);
};
return (
<div>
<h1>Blog Platform</h1>
<div>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Enter post title"
/>
<textarea
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="Write your post here"
/>
<button onClick={addPost}>Add Post</button>
</div>
<div className="blog-posts">
{posts.map((post) => (
<BlogPost key={post.id} post={post} onDelete={deletePost} />
))}
</div>
</div>
);
};
export default BlogPlatform;
In this example:
- We have a
BlogPost
component that displays the title, content, and a "Delete" button for a blog post. - The
BlogPlatform
component manages the list of posts using theuseState
hook. - The
addPost
function adds a new post to the list if both the title and content are valid. - The
deletePost
function removes a post from the list.
Please note that this is a simplified example and doesn't include features like authentication, user accounts, database integration, or rich text editing. In a real-world application, you would need to implement these and other features to create a complete blog platform.
GitHub Repository Viewer
Build a tool that allows users to search for GitHub repositories and view details like stars, forks, and contributors. Utilize the GitHub API for data retrieval.
Creating a GitHub Repository Viewer involves integrating with the GitHub API to fetch and display repository information. Here's a simplified example using React:
import React, { useState } from 'react';
const GitHubRepoViewer = () => {
const [username, setUsername] = useState('');
const [repositories, setRepositories] = useState([]);
const [error, setError] = useState(null);
const fetchRepositories = async () => {
try {
const response = await fetch(`https://api.github.com/users/${username}/repos`);
if (!response.ok) {
throw new Error('User not found');
}
const data = await response.json();
setRepositories(data);
setError(null);
} catch (error) {
setError(error.message);
setRepositories([]);
}
};
return (
<div>
<h1>GitHub Repository Viewer</h1>
<div>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Enter GitHub username"
/>
<button onClick={fetchRepositories}>Get Repositories</button>
</div>
{error && <div style={{ color: 'red' }}>{error}</div>}
<ul>
{repositories.map((repo) => (
<li key={repo.id}>
<a href={repo.html_url} target="_blank" rel="noopener noreferrer">
{repo.name}
</a>
</li>
))}
</ul>
</div>
);
};
export default GitHubRepoViewer;
In this example:
- We have a
GitHubRepoViewer
component that allows users to input a GitHub username and fetch their repositories. - The
fetchRepositories
function makes an API call to GitHub's API to retrieve the list of repositories for the given username. - If an error occurs during the API call (e.g., user not found), it updates the
error
state to display an error message. - The component renders an input field, a "Get Repositories" button, and a list of repositories.
Please note that you might need to handle pagination if a user has many repositories. Additionally, you should handle loading states and potentially add additional features like searching or sorting repositories.
Remember also to consider handling edge cases and potential errors during the API call.
Recipe Finder
Develop an application that allows users to search for recipes based on ingredients they have. Integrate with a recipe API to fetch and display results.
Creating a Recipe Finder app involves integrating with a recipe API to search and display recipes. Here's a simplified example using React:
import React, { useState } from 'react';
const RecipeFinder = () => {
const [ingredient, setIngredient] = useState('');
const [recipes, setRecipes] = useState([]);
const [error, setError] = useState(null);
const fetchRecipes = async () => {
try {
const response = await fetch(`https://api.spoonacular.com/recipes/findByIngredients`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
params: {
apiKey: 'YOUR_API_KEY', // Replace with your own API key
ingredients: ingredient,
number: 5 // Number of recipes to fetch
}
});
if (!response.ok) {
throw new Error('Error fetching recipes');
}
const data = await response.json();
setRecipes(data);
setError(null);
} catch (error) {
setError(error.message);
setRecipes([]);
}
};
return (
<div>
<h1>Recipe Finder</h1>
<div>
<input
type="text"
value={ingredient}
onChange={(e) => setIngredient(e.target.value)}
placeholder="Enter ingredient (e.g., chicken, onion)"
/>
<button onClick={fetchRecipes}>Find Recipes</button>
</div>
{error && <div style={{ color: 'red' }}>{error}</div>}
<ul>
{recipes.map((recipe) => (
<li key={recipe.id}>
<h3>{recipe.title}</h3>
<img src={recipe.image} alt={recipe.title} />
</li>
))}
</ul>
</div>
);
};
export default RecipeFinder;
In this example:
- We have a
RecipeFinder
component that allows users to input an ingredient and fetch recipes. - The
fetchRecipes
function makes an API call to the Spoonacular API to retrieve recipes based on the entered ingredient. - If an error occurs during the API call, it updates the
error
state to display an error message. - The component renders an input field, a "Find Recipes" button, and a list of recipes with their titles and images.
Please note that you'll need to obtain an API key from the Spoonacular API and replace 'YOUR_API_KEY'
with it.
Remember that you might need to handle pagination or implement additional features like sorting or filtering the recipes. Also, consider handling loading states for a smoother user experience.
Chat Application
Create a real-time chat application using technologies like Firebase for the backend. Users should be able to join different chat rooms or create private messages.
Creating a real-time chat application in React involves using a backend service, like Firebase or a WebSocket server, for handling real-time communication. Here's a simplified example using Firebase for the backend:
Step 1: Set Up a New React App
npx create-react-app ${APP_NAME}
Step 2: Set Up Firebase
- Go to the Firebase Console and create a new project.
- Set up Firebase Authentication and Firestore database.
- In your Firebase project, go to Project Settings > General > Your apps and click on the Web app (</>) to get your Firebase configuration.
Step 3: Install Firebase in Your React App
npm install firebase
Step 4: Create the Chat App Component
import React, { useState, useEffect } from 'react';
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
const firebaseConfig = {
// Your Firebase configuration here
};
firebase.initializeApp(firebaseConfig);
const ChatApp = () => {
const [messages, setMessages] = useState([]);
const [text, setText] = useState('');
const sendMessage = async () => {
if (text.trim() !== '') {
await firebase.firestore().collection('messages').add({
text: text,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
});
setText('');
}
};
useEffect(() => {
const unsubscribe = firebase.firestore().collection('messages').orderBy('timestamp').onSnapshot(snapshot => {
const newMessages = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
setMessages(newMessages);
});
return () => unsubscribe();
}, []);
return (
<div>
<h1>Chat App</h1>
<div>
<ul>
{messages.map(message => (
<li key={message.id}>{message.text}</li>
))}
</ul>
</div>
<div>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type a message..."
/>
<button onClick={sendMessage}>Send</button>
</div>
</div>
);
};
export default ChatApp;
Step 5: Use the Chat App Component
In your main application file (e.g., App.js
), import and use the ChatApp
component.
import React from 'react';
import ChatApp from './ChatApp';
function App() {
return (
<div className="App">
<ChatApp />
</div>
);
}
export default App;
Remember to replace firebaseConfig
with your actual Firebase configuration obtained from the Firebase Console.
Please note that this is a very basic example and lacks user authentication and more advanced features. In a real-world application, you would implement user authentication, handle user-specific messages, and potentially integrate more complex features like message history, user profiles, and more.