useEffect automatically recalculates user expenses whenever the users or expenses state changes. This ensures the displayed values stay up-to-date.
useEffect(() => {
const calculateUserExpenses = () => {
return users.map(user => ({
...user,
expense: expenses.reduce((total, expense) => {
const selectedItems = expense.items.filter(item =>
item.users.find(u => u.id === user.name && u.checked)
);
const totalValue = selectedItems.reduce((sum, item) => sum + (item.value / item.users.filter(u => u.checked).length), 0);
return total + totalValue;
}, 0)
}));
};
const newUserList = calculateUserExpenses();
if (JSON.stringify(newUserList) !== JSON.stringify(users)) {
setUsers(newUserList);
}
}, [expenses, users]);
-
Dependency Array: The second argument to useEffect is the dependency array [expenses, users]. This means that the effect will run whenever there are changes to either the expenses array or the users array.
-
Expense Calculation Logic: Inside the useEffect, there is a function called calculateUserExpenses that iterates over each user and calculates their total expenses based on the items in the expenses array.
Step-by-step:
-
Mapping Users:
return users.map(user => ({ ...user, expense: expenses.reduce((total, expense) => { // Calculate total expenses here }, 0) }));
-
Reducing Expenses:
expenses.reduce((total, expense) => { const selectedItems = expense.items.filter(item => item.users.find(u => u.id === user.name && u.checked) ); // ... }, 0)
For each expense, it checks which items are associated with the user. It does this by filtering expense.items for those items that have the user checked (u.checked).
-
Calculating Total Value:
const totalValue = selectedItems.reduce((sum, item) => sum + (item.value / item.users.filter(u => u.checked).length), 0); return total + totalValue;
It calculates the total expense for the user by summing up the values of the selected items divided by the number of users who are checked for that item. This allows for splitting the cost of expenses fairly among users.
- Setting State: After calculating the new expenses for users:
const newUserList = calculateUserExpenses();
if (JSON.stringify(newUserList) !== JSON.stringify(users)) {
setUsers(newUserList);
}
The new user list is compared to the existing users list. If there are changes (i.e., if the total expenses have been updated), it sets the new user list with updated expenses using setUsers(newUserList).