In this article we are going to create a budget tracker app that you can use to track your daily or weekly expenses.
We will be using these tools :
- Vite for our development environment. (Feel free to choose another environment that suits your preferences.)
- Bootstrap for CSS .
If you don’t know how to setup a React app using Vite – Click here and
to learn how to install Bootstrap in your React app – Click here .
How our app is going to appear ?
We will be making our Budget app in following steps :
- Creating UI .
- logical Part .
1. Creating UI
Note: If you would like to save time and avoid the task of creating a user interface, you can easily access the UI code from my GitHub repository. Simply Click here.
Now we are going to code for the UI part. First we will Open the src folder and go to App.jsx, this is the file from where we will start writing our code to create UI. Now we will create a <div> with the className of “container”, inside the “container” create a <h1> with the className “mt-3” and write “My Budget Planner” inside the opening and closing tag of h1.
We will create one more div inside the “container” with the className of “row mt-3” and put another div with the className of “col-sm” inside this div. Then we will create a folder called components, inside this folder we will create three files called “Budget.jsx”, “Remaining.jsx” and “Expense.jsx” then import it in App.jsx inside each “col-sm” div one by one.
App.jsx
import Budget from "./components/Budget";
import Expense from "./components/Expense";
import Remaining from "./components/Remaining";
function App() {
return (
<div className="container">
<h1 className="mt-3">My Budget Planner</h1>
<div className="row mt-3">
<div className="col-sm">
<Budget />
</div>
<div className="col-sm">
<Remaining />
</div>
<div className="col-sm">
<Expense />
</div>{" "}
</div>
</div>
);
}
export default App;
Now, we will go to the “Budget.jsx” and create a div with the className of “alert alert-secondary” and then put a span inside it.
Budget.jsx
import React, { useState } from "react";
const Budget = () => {
return (
<div className="alert alert-secondary p-3 d-flex align-items-center justify-content-between ">
<span className="">Budget : £ 2000</span>
</div>
);
};
export default Budget;
Now, we will go to the “Remaining.jsx” and create a div with the className of “alert alert-success” and put a span inside it.
Remaining.jsx
import React from "react";
const Remaining = () => {
return (
<div className="alert alert-success">
<span className="">Remaining : £ 2000</span>
</div>
);
};
export default Remaining;
Now, we will go to the “Expense.jsx” and create a div with the className of “alert alert-primary” and put a span inside it.
Expense.jsx
import React from "react";
const Expense = () => {
return (
<div className="alert alert-secondary">
<span className="">Spent so far : £ 0</span>
</div>
);
};
export default Expense;
This is how our Budget app is going to look so far :
Now we will come back to App.jsx, we will create a <h3> component under the
“row mt-3” div. Then we will create a new file called ExpenseList.jsx in our “component” folder.
In the “ExpenseList” component we will create a dummy array of expenses, then we will create a input field and a <ul>.
Inside the <ul> we will map over the array of expenses. For each expense
in the expenses
array, we will create a new component called ExpenseItem
and pass in two props: “name
” and “cost
“. The name
and cost
values will be extracted from the current expense
object using dot notation.
ExpenseList.jsx
import React from "react";
import ExpenseItem from "./ExpenseItem";
const ExpenseList = () => {
const expenses = [
{ id: 1234, name: "Shopping", cost: 100 },
{ id: 1235, name: "Holiday", cost: 70 },
{ id: 1236, name: "Transportation", cost: 90 },
{ id: 1237, name: "Magazine", cost: 40 },
{ id: 1238, name: "News paper", cost: 10 },
];
return (
<>
<input
type="text"
class="form-control mb-2 mr-sm-2"
placeholder="Type to search..."
/>
<ul className="list-group">
{expenses.map((expense) => (
<ExpenseItem name={expense.name} cost={expense.cost} />
))}
</ul>
</>
);
};
export default ExpenseList;
Now we will create ExpenseItem component, it will be a dumb component. It will receive data via props from its parent component and will use that data to render each expense.
ExpenseItem.jsx
import React from "react";
import { TiDelete } from "react-icons/ti";
const ExpenseItem = (props) => {
return (
<div>
<li className="list-group-item d-flex justify-content-between align-items-center">
{props.name}
<div>
<span style={{ marginRight: "100px" }}>£{props.cost}</span>
<TiDelete size="1.5em" />
</div>
</li>
</div>
);
};
export default ExpenseItem;
Next, we will create another file called AddExpenseForm.jsx inside our “component” folder. “AddExpenseForm.jsx” will contain a form component and the form will contain two “row” component.
First “row” component will have two input fields and the other “row” component will only have a button component “Save”.
AddExpenseForm.jsx
import React from "react";
const AddexpenseForm = () => {
return (
<form>
<div className="row">
<div className="col-sm col-lg-4">
<label for="name">Name</label>
<input
required="required"
type="text"
className="form-control"
id="name"
/>
</div>
<div className="col-sm col-lg-4">
<label for="cost">Cost</label>
<input
required="required"
type="number"
className="form-control"
id="cost"
/>
</div>
</div>
<div className="row mt-3">
<div className="col-sm">
<button type="submit" className="btn btn-primary">
Save
</button>
</div>
</div>
</form>
);
};
export default AddexpenseForm;
Next, we will move to the App.jsx, here we will add a <h3> named “Add Expense” and our <AddexpenseForm /> component.
App.jsx :
import AddexpenseForm from "./components/AddexpenseForm";
import Budget from "./components/Budget";
import Expense from "./components/Expense";
import ExpenseList from "./components/ExpenseList";
import Remaining from "./components/Remaining";
function App() {
return (
<div className="container">
<h1 className="mt-3">My Budget Planner</h1>
<div className="row mt-3">
<div className="col-sm">
<Budget />
</div>
<div className="col-sm">
<Remaining />
</div>
<div className="col-sm">
<Expense />
</div>{" "}
</div>
<h3 className="mt-3">Expenses</h3>
<div className="row mt-3">
<div className="col-sm">
<ExpenseList />
</div>
</div>
<h3 className="mt-3">Add Expense</h3>
<div className="row mt-3">
<div className="col-sm">
<AddexpenseForm />
</div>
</div>
</div>
);
}
export default App;
Now, we will add edit button and edit functionality in our Budget component.
The functionality will be like Whenever we will click on the Edit button an input field will open where we can edit our budget and save that.
Budget.jsx :
import React, { useState } from "react";
const Budget = () => {
const [isEditClicked, setIsEditClicked] = useState(false);
return (
<>
<div className="alert alert-secondary p-3 d-flex align-items-center justify-content-between ">
{isEditClicked ? (
<>
<input
required="required"
type="number"
className="form-control mr-3"
id="name"
placeholder="type your Budget"
/>
<button type="button" class="btn btn-primary">
Save
</button>
</>
) : (
<>
{" "}
<span className="">Budget : £ 2000</span>
<button
onClick={() => setIsEditClicked(!isEditClicked)}
type="button"
class="btn btn-primary"
>
Edit
</button>
</>
)}
</div>
</>
);
};
export default Budget;
This is how our Budget app should appear after completion of UI part :
Now we have completed the UI part.
2. Logical Part
Our logical part will contain following 6 steps :
- Edit Budget .
- Adding Expense .
- Mapping ExpenseList .
- Delete Expense .
- Search Expense.
- Calculating Remaining amount.
- Calculating Expensed amount .
Step 1 – Edit Budget
Here we will add a functionality in which users can edit the Budget according to their preferences, to achieve that we will first create two state variables called “isEditClicked” and “budget”. Where “isEditClicked” is a boolean with the initial value of “false” that tells us whether the user has clicked on the edit button or not. “Budget” is the value that the user wants to set for their Budget. Budget has the initial value of 2000.
We will use Context API to pass data down in the components because it is one of the easiest way. Now we will create a context object named “budgetContext” that will contain the data we want to share and export it.
Then, will use the `Provider
` component to wrap the components that need access to the data and we will put all our data which we want to pass inside the value element in <budgetContext.Provider>.
App.jsx :
const budgetContext = createContext();
function App() {
const [isEditClicked, setIsEditClicked] = useState(false);
const [budget, setBudget] = useState(2000);
return (
// <div className="container">
<budgetContext.Provider
value={{
isEditClicked,
setIsEditClicked,
budget,
setBudget,
}}
>
// <h1 className="mt-3">My Budget Planner</h1>
// <div className="row mt-3">
// <div className="col-sm">
// <Budget budgetContext={budgetContext} />
// </div>
// <div className="col-sm">
// <Remaining />
// </div>
// <div className="col-sm">
// <Expense />
// </div>{" "}
// </div>
// <h3 className="mt-3">Expenses</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <ExpenseList />
// </div>
// </div>
// <h3 className="mt-3">Add Expense</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <AddexpenseForm />
// </div>
// </div>
</budgetContext.Provider>
// </div>
);
}
export default App;
Next, we take the Budget value that the user entered and use it to update the input field. We do this by setting the “budget” state variable to the current value of the input field using the “setBudget” function.
Then we create a function called “handleSaveClick” and give it to the onClick() event of our “Save” button component. In “handleSaveClick()” we just update the “isEditClicked” with it’s opposite value.
Budget.jsx :
// import React, { useState } from "react";
import { useContext } from "react";
import { budgetContext } from "../App";
const Budget = () => {
const { isEditClicked, setIsEditClicked, budget, setBudget } =
useContext(budgetContext);
const handleSaveClick = () => {
setIsEditClicked(!isEditClicked);
};
return (
<>
// <div className="alert alert-secondary p-3 d-flex align-items-center justify-content-between ">
// {isEditClicked ? (
// <>
// <input
// required="required"
// type="number"
// className="form-control mr-3"
// id="name"
// placeholder="Enter Budget"
value={budget}
onChange={(e) => setBudget(e.target.value)}
// />
// <button
onClick={handleSaveClick}
// type="button"
// className="btn btn-primary"
// >
// Save
// </button>
// </>
// ) : (
// <>
// {" "}
// <span className="">Budget : £ {budget}</span>
// <button
// onClick={() => setIsEditClicked(!isEditClicked)}
// type="button"
// className="btn btn-primary"
// >
// Edit
// </button>
// </>
// )}
// </div>
// </>
);
};
export default Budget;
Step 2 – Adding Expense
In this step we will store the value which the user entered in the “Name” and “Cost” input field. To do that we will go to the App.jsx and create two state variables called “name” and “cost”.
The “name” variable will contain the value which user entered in the the “Name” input in our AddExpense part and “cost” will contain the value which user entered in the “Cost” input.
Now we will pass the “name”, “cost”, varibles and “setName”, “setCost” functions to the value element of <budgetContext.Provider>, and will access “name” and “cost” in our ExpenseList (so we can map them to show user’s expense list) and in AddExpenseForm component.(so that the input filelds of our “AddexpenseForm“ component could update the value of our state variables with their onChange() event)
Next, we will create a function called “handleSave” and pass it to the value element of <budgetContext.Provider> so that we can access it in our AddexpenseForm component and give it to the Onclick() event of “Save” button.
App.jsx :
// export const budgetContext = createContext();
function App() {
// const [isEditClicked, setIsEditClicked] = useState(false);
// const [budget, setBudget] = useState(2000);
const [name, setName] = useState();
const [cost, setCost] = useState();
const handleSave = (e) => {
e.preventDefault();
};
return (
// <div className="container">
<budgetContext.Provider
value={{
// isEditClicked,
// setIsEditClicked,
// budget,
// setBudget,
name,
cost,
setName,
setCost,
handleSave,
}}
>
// <h1 className="mt-3">My Budget Planner</h1>
// <div className="row mt-3">
// <div className="col-sm">
// <Budget />
// </div>
// <div className="col-sm">
// <Remaining />
// </div>
// <div className="col-sm">
// <Expense />
// </div>{" "}
// </div>
// <h3 className="mt-3">Expenses</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <ExpenseList />
// </div>
// </div>
// <h3 className="mt-3">Add Expense</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <AddexpenseForm />
// </div>
// </div>
</budgetContext.Provider>
// </div>
);
}
export default App;
AddexpenseForm.jsx :
We will access the value using useContext.
// import React from "react";
import { useContext } from "react";
import { budgetContext } from "../App";
const AddexpenseForm = () => {
const { setName, setCost, handleSave } = useContext(budgetContext);
return (
// <form>
// <div className="row">
// <div className="col-sm col-lg-4">
// <label htmlFor="name">Name</label>
// <input
// required="required"
// type="text"
// className="htmlForm-control"
// id="name"
onChange={(event) => setName(event.target.value)}
// />
// </div>
// <div className="col-sm col-lg-4">
// <label htmlFor="cost">Cost</label>
// <input
// required="required"
// type="number"
// className="htmlForm-control"
// id="cost"
onChange={(event) => setCost(event.target.value)}
/>
// </div>
// </div>
// <div className="row mt-3">
// <div className="col-sm">
// <button
onClick={handleSave}
// type="submit"
// className="btn btn-primary"
// >
// Save
// </button>
// </div>
// </div>
// </form>
);
};
export default AddexpenseForm;
Step 3 – Mapping ExpenseList
To map trough List of Expenses we will create a state variable named “expenseList” with the initial value of empty Array “[ ]” in our App.jsx and we will bring the dummy expenses from the ExpenseList.jsx to App.jsx.
Next, we will create a useEffect() hook in our App.jsx which we will setExpenseList
function is called with the value [...expenses]
as its argument. This creates a new array with the same values as “expenses
” and passes it to the “setExpenseList
” function, which updates the expenseList
state variable of the component.
Overall, this code updates the expenseList
state variable with the value of the expenses
variable when the component mounts. It’s important to note that we haven’t specify any dependencies, so this code will only run once and won’t update the “expenseList
” state variable if the expenses
variable changes later and that’s what we want.
Now we will come to our “handleSave” function in App.jsx. Inside “handleSave” we will create a variable named “rendomeID” which will be generated new every time whenever the function “handleSave” is called.
Next, under the “rendomeID” variable we will updates the expenseList
state variable of the component using the setExpenseList
function. It does this by creating a new array with the current “expenseList
” array spread using the spread operator ...expenseList
, and add a new object to the end of the array.
The new object contains three properties: id
(which is the random ID generated earlier), name
(which is likely a name entered into a form input field), and cost
(which is likely a cost entered into another form input field). Then we will pass our state variable “expenseList” to <budgetContext.Provider> and access it in our ExpenseList.jsx.
App.jsx :
// export const budgetContext = createContext();
function App() {
// const [isEditClicked, setIsEditClicked] = useState(false);
// const [budget, setBudget] = useState(2000);
// const [name, setName] = useState();
// const [cost, setCost] = useState();
const [expenseList, setExpenseList] = useState([]);
const expenses = [
{ id: 1, name: "Shopping", cost: 50 },
{ id: 2, name: "Holiday", cost: 300 },
{ id: 3, name: "Transportation", cost: 70 },
{ id: 4, name: "Fuel", cost: 40 },
{ id: 5, name: "Child Care", cost: 500 },
];
useEffect(() => {
setExpenseList([...expenses]);
}, []);
const handleSave = (e) => {
// e.preventDefault();
const rendomeID = Math.floor(Math.random() * 1000);
setExpenseList([...expenseList, { id: rendomeID, name: name, cost: cost }]);
};
return (
// <div className="container">
<budgetContext.Provider
// value={{
// isEditClicked,
// setIsEditClicked,
// budget,
// setBudget,
// name,
// cost,
// setName,
// setCost,
handleSave,
expenseList,
}}
>
// <h1 className="mt-3">My Budget Planner</h1>
// <div className="row mt-3">
// <div className="col-sm">
// <Budget />
// </div>
// <div className="col-sm">
// <Remaining />
// </div>
// <div className="col-sm">
// <Expense />
// </div>{" "}
// </div>
// <h3 className="mt-3">Expenses</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <ExpenseList />
// </div>
// </div>
// <h3 className="mt-3">Add Expense</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <AddexpenseForm />
// </div>
// </div>
</budgetContext.Provider>
// </div>
);
}
export default App;
We will access our variable “expenseList” here in the ExpenseList.jsx and iterate over it using ‘map’.
ExpenseList.jsx :
import React, { useContext, useState } from "react";
import ExpenseItem from "./ExpenseItem";
import { budgetContext } from "../App";
const ExpenseList = () => {
const { expenseList } = useContext(budgetContext);
return (
<>
// <input
// type="text"
// className="form-control mb-2 mr-sm-2"
// placeholder="Type to search..."
// />
// <ul className="list-group">
{expenseList.map((expense, id) => (
<ExpenseItem
key={id}
id={expense.id}
name={expense.name}
cost={expense.cost}
/>
))}
// </ul>
// </>
);
};
export default ExpenseList;
Now write something in the “Name” and “Cost” input and click on the “Save” button and you will see that the value has added to the expense list.
Step 4 -Delete Expense
Now we will add a new feature to our application which is deleting expense. To do that we will first create a function called “handleDelete”.
handleDelete
takes an argument “deletedID
“, which represents the ID of the expense to be deleted. Then we will create “expenseList.filter(...)
” which creates a new array that includes all the expenses from expenseList
except the one with the specified deletedID
. This is done by using the filter
function to iterate over each element in the expenseList
array and create a new array with only the elements that meet the filter condition.
The filter condition will be (ele) => deletedID !== ele.id
, which returns true
for any element whose ID does not match the deletedID
argument and then The new array will be assigned to a variable list
and the end we will update the state variable with the value list.
Next, we will pass the “handleDelete” function to <budgetContext.Provider> and access it in ExpenseItem component, then pass it to the onClick() event of the button component <TiDelete>, the onClick() event will provide the ID of the expense which was clicked.
App.jsx :
// export const budgetContext = createContext();
function App() {
// const [isEditClicked, setIsEditClicked] = useState(false);
// const [budget, setBudget] = useState(2000);
// const [name, setName] = useState();
// const [cost, setCost] = useState();
// const [expenseList, setExpenseList] = useState([]);
// const expenses = [
// { id: 1, name: "Shopping", cost: 50 },
// { id: 2, name: "Holiday", cost: 300 },
// { id: 3, name: "Transportation", cost: 70 },
// { id: 4, name: "Fuel", cost: 40 },
// { id: 5, name: "Child Care", cost: 500 },
// ];
// useEffect(() => {
// setExpenseList([...expenses]);
// }, []);
// const handleSave = (e) => {
// e.preventDefault();
// const rendomeID = Math.floor(Math.random() * 1000);
// setExpenseList([...expenseList, { id: rendomeID, name: name, cost: cost }]);
// };
const handleDelete = (deletedID) => {
const list = expenseList.filter((ele) => deletedID !== ele.id);
setExpenseList(list);
};
return (
// <div className="container">
<budgetContext.Provider
// value={{
// isEditClicked,
// setIsEditClicked,
// budget,
// setBudget,
// name,
// cost,
// setName,
// setCost,
// handleSave,
// expenseList,
handleDelete,
}}
>
// <h1 className="mt-3">My Budget Planner</h1>
// <div className="row mt-3">
// <div className="col-sm">
// <Budget />
// </div>
// <div className="col-sm">
// <Remaining />
// </div>
// <div className="col-sm">
// <Expense />
// </div>{" "}
// </div>
// <h3 className="mt-3">Expenses</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <ExpenseList />
// </div>
// </div>
// <h3 className="mt-3">Add Expense</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <AddexpenseForm />
// </div>
// </div>
</budgetContext.Provider>
// </div>
);
}
export default App;
ExpenseItem.jsx :
import React, { useContext } from "react";
import { TiDelete } from "react-icons/ti";
import { budgetContext } from "../App";
const ExpenseItem = (props) => {
const { handleDelete } = useContext(budgetContext);
return (
<div>
// <li className="list-group-item d-flex justify-content-between align-items-center">
// {props.name}
// <div>
// <span style={{ marginRight: "100px" }}>£{props.cost}</span>
<TiDelete
onClick={() => handleDelete(props.id)}
size="1.5em"
/>
// </div>
// </li>
// </div>
);
};
export default ExpenseItem;
Step 5 – Search Expense
Remember we created a search bar in our ExpenseList component so now it’s time to use it. This search bar will sort expenses based on the value entered by the user in the input field. To do that we will first create a state variable named “text” in our App.jsx.
Now we will create a new array called “filteredExpenses” by filtering the “expenseList” array. The filter function will take a callback function that checks whether each element in the “expenseList” array matches the search text entered by the user.
The callback function will check if the lowercase version of the “name” property of each expense object includes the lowercase version of the “text” parameter passed to the function.
If an element in the “expenseList” array satisfies this condition, it will be included in the “filteredExpenses” array, otherwise, it will be excluded. Then we will pass “filteredExpenses” and “setText” to <budgetContext.Provider> and access them in the “ExpenseList” component.
App.jsx :
// export const budgetContext = createContext();
function App() {
// const [isEditClicked, setIsEditClicked] = useState(false);
// const [budget, setBudget] = useState(2000);
// const [name, setName] = useState();
// const [cost, setCost] = useState();
// const [expenseList, setExpenseList] = useState([]);
const [text, setText] = useState("");
// const expenses = [
// { id: 1, name: "Shopping", cost: 50 },
// { id: 2, name: "Holiday", cost: 300 },
// { id: 3, name: "Transportation", cost: 70 },
// { id: 4, name: "Fuel", cost: 40 },
// { id: 5, name: "Child Care", cost: 500 },
// ];
// useEffect(() => {
// setExpenseList([...expenses]);
// }, []);
// const handleSave = (e) => {
// e.preventDefault();
// const rendomeID = Math.floor(Math.random() * 1000);
// setExpenseList([...expenseList, { id: rendomeID, name: name, cost: cost }]);
// };
// const handleDelete = (deletedID) => {
// const list = expenseList.filter((ele) => deletedID !== ele.id);
// setExpenseList(list);
// };
let filteredExpenses = expenseList.filter((ele) =>
ele.name.toLowerCase().includes(text.toLowerCase())
);
return (
// <div className="container">
<budgetContext.Provider
// value={{
// isEditClicked,
// setIsEditClicked,
// budget,
// setBudget,
// name,
// cost,
// setName,
// setCost,
// handleSave,
// expenseList,
// handleDelete,
setText,
filteredExpenses,
}}
>
// <h1 className="mt-3">My Budget Planner</h1>
// <div className="row mt-3">
// <div className="col-sm">
// <Budget />
// </div>
// <div className="col-sm">
// <Remaining />
// </div>
// <div className="col-sm">
// <Expense />
// </div>{" "}
// </div>
// <h3 className="mt-3">Expenses</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <ExpenseList />
// </div>
// </div>
// <h3 className="mt-3">Add Expense</h3>
// <div className="row mt-3">
// <div className="col-sm">
// <AddexpenseForm />
// </div>
// </div>
</budgetContext.Provider>
// </div>
);
}
export default App;
We will access “setText” and “filteredExpenses” here in the ExpenseList component. Then we will pass “setText” to the onChange() event of our input component(search bar).
Here In the ExpenseList component, we have a list of expenses called “expenseList”. We are currently using it to display all the expenses in the component. We want to update it to only display expenses that match the user’s search term.
To do this, we will replace “expenseList” with “filteredExpenses”, which we will access through the userContext. “filteredExpenses” is the result of filtering the “expenseList” based on the user’s search term.
Once we make this change, users can type a relevant word in the search bar and the expenses will be filtered and displayed based on their search term.
ExpenseList.jsx :
import React, { useContext, useState } from "react";
import ExpenseItem from "./ExpenseItem";
import { budgetContext } from "../App";
const ExpenseList = () => {
const { setText, filteredExpenses } = useContext(budgetContext);
return (
<>
<input
onChange={(event) => setText(event.target.value)}
type="text"
className="form-control mb-2 mr-sm-2"
placeholder="Type to search..."
/>
<ul className="list-group">
{filteredExpenses.map((expense, id) => (
<ExpenseItem
key={id}
id={expense.id}
name={expense.name}
cost={expense.cost}
/>
))}
</ul>
</>
);
};
export default ExpenseList;
Step 6 – Calculating Remaining budget
Now, we will use the “reduce()
” method to calculate the total cost of all the expenses. The “reduce()
” method will take a function as its argument, which is called for each element in the array.
The function passed to “reduce()
” will take two arguments: acc
(short for accumulator) and curr
(short for current). The acc
argument will keep track of the running total of the cost of all the expenses, and the curr
argument represents the current expense being processed.
The function then returns the sum of the current expense’s cost and the running total (acc + curr.cost
). This returned value is then used as the new value of the acc
argument in the next iteration of the loop, until all expenses in the filtered list have been processed.
Finally, the resulting sum is stored in the spentSoFar
variable, which will use to display the total amount spent so far.
Then we will pass spentSoFar variable to <budgetContext.Provider> and will access it in Remaining.jsx to show the remaining budget on the screen.
App.jsx :
// let filteredExpenses = expenseList.filter((ele) => {
// return ele.name.toLowerCase().includes(text.toLowerCase());
// });
let spentSoFar = filteredExpenses.reduce((acc, curr) => acc + curr.cost, 0);
return (
// <div className="container">
<budgetContext.Provider
value={{
// isEditClicked,
// setIsEditClicked,
// budget,
// setBudget,
// name,
// cost,
// setName,
// setCost,
// handleSave,
// expenseList,
// handleDelete,
// setText,
filteredExpenses,
spentSoFar,
}}
// >
We will access “spentSoFar” and “budget” varible here in the Remaining.jsx and will use them in our span tag to show them on the screen.
Remaining.jsx :
import React, { useContext } from "react";
import { budgetContext } from "../App";
const Remaining = () => {
const { spentSoFar, budget } = useContext(budgetContext);
return (
<div className="alert alert-success">
<span className="">Remaining : £ {budget - spentSoFar}</span>
</div>
);
};
export default Remaining;
Step 7 – Calculating Spent So far amount
We have calculated the spent so far amount so we just need to display it on to the screen and for that we will access it through the useContext() in our “Expense.jsx”.
Expense.jsx :
import React, { useContext } from "react";
import { budgetContext } from "../App";
const Expense = () => {
const { spentSoFar } = useContext(budgetContext);
return (
<div className="alert alert-secondary">
<span className="">Spent so far : £ {spentSoFar}</span>
</div>
);
};
export default Expense;
Now you are ready to use fully functional Budget application that you can use to track your weekly or monthly expense.
ALSO SEE- MAKE SIMPLE TODO APP USING REACT.