i have the following react component
function App() {
const [users, setUsers] = useState(test);
const [name, setName] = useState("");
const [amount, setAmount] = useState(0);
const [total, setTotal] = useState(0);
const [usersNames, setUsersName] = useState([])
const addUser = () => {
setUsers([...users, { name: name, amount: amount }]);
setName("");
setAmount(0);
};
const calculate = () => {
const total = users.reduce((acc, user) => acc + user.amount, 0);
const perPerson = total / users.length
const newUsers = users.map(user => {
return {...user, balance: user.amount - perPerson, transactions: []}
})
setTotal(total);
setUsersName(users.map(user => user.name));
setUsers(newUsers);
const {debtors, creditors} = distribute(newUsers);
retribute(debtors, creditors);
}
const distribute = (usersList) => {
const debtors = [];
const creditors = [];
usersList.forEach(({name, balance}) => {
if (balance < 0){
debtors.push(name);
}
if (balance > 0){
creditors.push(name);
}
})
return {
debtors: debtors,
creditors: creditors,
}
}
const retribute = (debtorsList, creditorsList) => {
const usersUpdated = [];
debtorsList.forEach(debtorName => {
const debtorPos = usersNames.indexOf(debtorName);
const debtor = users[debtorPos];
creditorsList.forEach(name => {
if (debtor.balance < 0){
const creditorPos = usersNames.indexOf(name);
const creditor = users[creditorPos];
if (creditor.balance >= debtor.balance * -1){
creditor.balance -= debtor.balance * -1;
debtor.transactions.push(`${debtor.name} gives ${creditor.name}: ${debtor.balance * -1}`)
debtor.balance = 0;
}
if (creditor.balance < debtor.balance * -1){
debtor.balance = debtor.balance + creditor.balance;
debtor.transactions.push(`${debtor.name} gives ${creditor.name}: ${creditor.balance}`)
creditor.balance = 0;
}
}
})
usersUpdated.push(debtor);
})
console.log(usersUpdated);
}
...
The ui is very simple just a 2 inputs (name, amount) a button to add to a list and then another button to trigger the calculate function. The problem i’m confronting is the following: When first-clicking the calculate button i recieve this error:
Uncaught TypeError: Cannot read properties of undefined (reading 'balance')
at App.jsx:63:20
at Array.forEach (<anonymous>)
at App.jsx:62:21
at Array.forEach (<anonymous>)
at retribute (App.jsx:59:17)
at calculate (App.jsx:32:5)
at HTMLUnknownElement.callCallback2 (react-dom.development.js:4164:14)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:16)
at invokeGuardedCallback (react-dom.development.js:4277:31)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:25)
and then, if i clicked it again, it works properly.
I’m very new in React and things are not going as expected. Thanks to whoever reply and try to help me!
2
Answers
Try change this:
const [users, setUsers] = useState(test);
to something like:
const [users, setUsers] = useState([]);
I see that you have functions which set state and do other computations. But that you have not initialized the data for all of your states. Just the
users
.I cannot see your JSX code or the entirety of your component, but I’m going to assume that your functions are invoked only on
onClick
.You have said that on initial button click, an error thrown. But not on the second click.
This is possibly because of
calculate
function is called somewhere in your code when the button is clicked. Which sets all of your states.You could probably fix this issue by properly setting up data for your different states on component mount. This would be the recommended way.
…But you could also probably call your
calculate
function inside a useEffect, to set up your states on component mount.