Building a React Expense Tracker App
Abhishek Gurjar
Posted on September 10, 2024
Introduction
In this tutorial, we will create an Expense Tracker Web Application using React. This project will help you understand state management, event handling, and dynamic list updates in React. It’s ideal for beginners aiming to strengthen their knowledge of React development by building a practical and useful application.
Project Overview
The Expense Tracker application allows users to keep track of their income and expenses. It helps manage financial data by categorizing and calculating income, expenses, and the total balance. This project showcases the use of React for managing state and handling user input efficiently.
Features
- Add Transactions: Users can add income or expense transactions.
- Track Balance: Users can view their total balance and track changes dynamically.
- Delete Transactions: Users can remove transactions from the list.
-
Local Storage: Transactions are persisted across page reloads using
localStorage
.
Technologies Used
- React: To build the user interface and manage component state.
- CSS: To style the application.
- JavaScript: To handle the application's core logic.
Project Structure
The project structure follows a typical React project layout:
├── public
├── src
│ ├── components
│ │ ├── TransactionList.jsx
│ │ ├── TransactionItem.jsx
│ │ ├── AddTransaction.jsx
│ ├── App.jsx
│ ├── App.css
│ ├── index.js
│ └── index.css
├── package.json
└── README.md
Key Components
- TransactionList.jsx: Displays and manages the list of transactions.
- TransactionItem.jsx: Represents an individual transaction.
- AddTransaction.jsx: Handles adding new transactions (income or expense).
Code Explanation
TransactionList Component
This component handles displaying the transactions and managing the state of all transactions.
import { useState, useEffect } from "react";
import TransactionItem from "./TransactionItem";
const TransactionList = () => {
const [transactions, setTransactions] = useState([]);
useEffect(() => {
const savedTransactions = JSON.parse(localStorage.getItem("transactions")) || [];
setTransactions(savedTransactions);
}, []);
useEffect(() => {
localStorage.setItem("transactions", JSON.stringify(transactions));
}, [transactions]);
const deleteTransaction = (index) => {
const newTransactions = transactions.filter((_, i) => i !== index);
setTransactions(newTransactions);
};
return (
<div className="transaction-list">
<h2>Transaction History</h2>
<ul>
{transactions.map((transaction, index) => (
<TransactionItem
key={index}
transaction={transaction}
deleteTransaction={deleteTransaction}
/>
))}
</ul>
</div>
);
};
export default TransactionList;
TransactionItem Component
The TransactionItem
component represents an individual transaction, including options to delete it.
const TransactionItem = ({ transaction, deleteTransaction }) => {
const sign = transaction.amount < 0 ? "-" : "+";
return (
<li className={transaction.amount < 0 ? "expense" : "income"}>
{transaction.text}
<span>{sign}${Math.abs(transaction.amount)}</span>
<button onClick={deleteTransaction}>Delete</button>
</li>
);
};
export default TransactionItem;
AddTransaction Component
This component manages adding new transactions, allowing users to input income or expense data.
import { useState } from "react";
const AddTransaction = ({ addTransaction }) => {
const [text, setText] = useState("");
const [amount, setAmount] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
const transaction = { text, amount: +amount };
addTransaction(transaction);
setText("");
setAmount("");
};
return (
<div>
<h2>Add New Transaction</h2>
<form onSubmit={handleSubmit}>
<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 type="submit">Add Transaction</button>
</form>
</div>
);
};
export default AddTransaction;
App Component
The App.jsx
serves as the root of the application, rendering the TransactionList
and AddTransaction
components.
import { useState } from "react";
import TransactionList from './components/TransactionList';
import AddTransaction from './components/AddTransaction';
import './App.css';
const App = () => {
const [transactions, setTransactions] = useState([]);
const addTransaction = (transaction) => {
setTransactions([...transactions, transaction]);
};
return (
<div className="app">
<h1>Expense Tracker</h1>
<TransactionList transactions={transactions} />
<AddTransaction addTransaction={addTransaction} />
<div className="footer">
<p>Made with ❤️ by Abhishek Gurjar</p>
</div>
</div>
);
};
export default App;
CSS Styling
The CSS ensures the application looks clean and user-friendly.
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
}
.app {
width: 400px;
margin: 50px auto;
background-color: #fff;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
text-align: center;
}
input {
width: calc(100% - 10px);
padding: 5px;
margin-bottom: 10px;
}
button {
width: 100%;
padding: 10px;
background-color: #007BFF;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.transaction-list ul {
list-style: none;
padding: 0;
}
.transaction-list li {
background-color: #f9f9f9;
margin: 5px 0;
padding: 10px;
border-left: 5px solid green;
}
.transaction-list li.expense {
border-left: 5px solid red;
}
.transaction-list span {
float: right;
}
button {
float: right;
background-color: red;
color: white;
padding: 5px;
}
.footer{
text-align: center;
margin: 40px;
}
Installation and Usage
To get started, clone the repository and install the dependencies:
git clone https://github.com/abhishekgurjar-in/expense-tracker.git
cd expense-tracker
npm install
npm start
The application will start running at http://localhost:3000
.
Live Demo
Check out the live demo of the Expense Tracker here.
Conclusion
The Expense Tracker project demonstrates how to manage lists and state effectively in React. It’s a great way to learn how to build dynamic applications with persistent data storage using localStorage
.
Credits
- Inspiration: Built with the idea of helping users track their financial transactions.
Author
Abhishek Gurjar is a dedicated web developer passionate about creating practical and functional web applications. Check out more of his projects on GitHub.
Posted on September 10, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.