当调用 HandlePayNow 函数时,它会执行所有预期的功能,但随后会导致系统崩溃。它将订单数据发送到 API,API 记录它并返回一条成功消息,该函数获取此成功消息,它显示带有正确数字的“请显示付款”警报(与单击按钮时提交的数字相匹配)日志中存在的内容),然后崩溃并提供错误消息:
Cannot read properties of undefined (reading 'toFixed')
TypeError: Cannot read properties of undefined (reading 'toFixed')
at http://localhost:3000/static/js/bundle.js:783:58
at Array.map (\<anonymous\>)
at App (http://localhost:3000/static.js.bundle.js:768:32)
at renderWithHooks (http://localhost:3000/static/js/bundle.js:22965:22)
at updateFunctionComponent (http://localhost:3000/static/js/buindle.js:27559:20)
at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:12557:18)
at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:12601:20)
at invokeGuardedcallback (http://localhost:3000/static/js/bundle.js:12658:35)
at beginWork$1 (http://localhost:3000/static/js/bundle.js:32532:11)
在修改CalculateRunningTotal 函数之前,这种情况不会发生。我大约 99% 确信(当我获得令人惊叹的 StackOverflow 社区的帮助时,情况总是如此),这只是一个愚蠢的例子,我公然忽视了一些非常明显的事情。我的直觉告诉我这与异步中重置小计状态的方式有关,但坦率地说,我在 JS 方面很糟糕。这不是我的包。如果有人能解释我的愚蠢,我将不胜感激。
所有相关功能:
const logToConsole = (message) => {
setConsoleLogs((prevLogs) => [...prevLogs, message]);
};
useEffect(() => {
const customConsoleLog = console.log;
console.log = (message) => logToConsole(message);
return () => {
console.log = customConsoleLog;
};
}, []);
const calculateItemTotal = (item) => {
let sizePrice = getSizePrice(item.size);
let flavorPrice = item.flavors.length * 0.89;
return sizePrice + flavorPrice + item.toppingsPrice;
};
const calculateRunningTotal = () => {
let total = 0;
for (const itemTotal of runningTotals) {
total += itemTotal;
}
if (selectedDiscount) {
const discount = discounts.find((discount) => discount.name === selectedDiscount);
if (discount) {
const discountMultiplier = 1 - discount.discount;
total *= discountMultiplier;
}
}
// Check if total is NaN before applying toFixed
return isNaN(total) ? 0 : total.toFixed(2);
};
const handleAddToOrder = () => {
if (!selectedSize) {
alert("Select a Size!");
return;
}
const item = {
size: selectedSize,
flavors: selectedFlavors,
toppingsPrice: toppingsPrice,
};
setOrderItems((prevItems) => [...prevItems, item]);
setSubtotal((prevSubtotal) => prevSubtotal + calculateItemTotal(item));
setRunningTotals((prevTotals) => [...prevTotals, calculateItemTotal(item)]);
setSelectedSize(null);
setSelectedFlavors([]);
setToppingsPrice(0);
setSyrupToppings((prevToppings) =>
prevToppings.map((topping) => ({
...topping,
isActive: false,
}))
);
};
const getSizePrice = (size) => {
switch (size) {
case 'Small':
return 2.49;
case 'Medium':
return 3.29;
case 'Large':
return 4.19;
default:
return 0;
}
};
const handleAddTopping = (price) => {
setToppingsPrice((prevPrice) => prevPrice + price);
};
const calculateCurrentItem = () => {
let sizePrice = selectedSize ? getSizePrice(selectedSize) : 0;
let flavorPrice = selectedFlavors.length * 0.89;
let total = sizePrice + flavorPrice + toppingsPrice;
if (selectedDiscount) {
const discount = discounts.find((discount) => discount.name === selectedDiscount);
if (discount) {
const discountMultiplier = 1 - discount.discount;
total *= discountMultiplier;
}
}
return total.toFixed(2);
};
const handleRemoveOrder = (index) => {
const removedItem = orderItems[index];
const removedItemTotal = calculateItemTotal(removedItem);
setOrderItems((prevItems) => prevItems.filter((_, i) => i !== index));
setRunningTotals((prevTotals) => prevTotals.filter((_, i) => i !== index));
setSubtotal((prevSubtotal) => {
const newSubtotal = prevSubtotal - removedItemTotal;
return newSubtotal < 0 ? 0 : newSubtotal;
});
};
const handlePayNow = async () => {
if (orderItems.length === 0) {
alert("No items in the order!"); // Make user select more than 0 items
return;
}
let name = prompt("Enter customer name:"); // Prompt for customer name
while (!name) {
name = prompt("Enter customer name:"); // Re-prompt for customer name
}
setCustomerName(name); // Set the customer name
// Reset the subtotal
setSubtotal(0);
let originalTotal = subtotal;
let discountAmount = 0;
let discountType = "None"; // Default value for discount type
if (selectedDiscount) {
const discount = discounts.find((discount) => discount.name === selectedDiscount);
if (discount) {
const discountMultiplier = 1 - discount.discount;
discountAmount = originalTotal - (originalTotal * discountMultiplier);
originalTotal = originalTotal * discountMultiplier;
discountType = discount.name; // Store the discount type
}
}
const logs = [];
logs.push('');
logs.push('');
logs.push(`Size: ${selectedSize ? selectedSize.charAt(0).toUpperCase() + selectedSize.slice(1) : null}`);
const flavorsText = selectedFlavors.length > 0 ? selectedFlavors.join(", ") : "None";
logs.push(`Flavors: ${flavorsText}`);
const nonCustomAddIns = syrupToppings.filter((topping) => topping.isActive && !topping.custom);
const selectedAddIns = nonCustomAddIns.map((topping) => topping.name);
if (selectedAddIns.length > 0) {
logs.push(`Add-ins: ${selectedAddIns.join(", ")}`);
} else {
logs.push("Add-ins: None");
}
const tax = (originalTotal * 0.056).toFixed(2);
const totalWithTax = (parseFloat(originalTotal) + parseFloat(tax)).toFixed(2);
logs.push('');
logs.push(`Subtotal: $${originalTotal.toFixed(2)}`);
logs.push(`Tax: $${tax}`);
logs.push(`Total: $${totalWithTax}`);
logs.push('');
setConsoleLogs(logs); // Update the console logs with the new order information
const updatedToppings = syrupToppings.map((topping) => {
const updatedTopping = { ...topping };
if (updatedTopping.isActive) {
updatedTopping.soldCount += 1;
}
updatedTopping.isActive = false;
return updatedTopping;
});
setSyrupToppings(updatedToppings);
setSelectedSize(null); // Reset selectedSize to null
setSelectedFlavors([]); // Reset selectedFlavors to an empty array
setToppingsPrice(0); // Reset toppingsPrice to 0
setSelectedDiscount(null); // Reset selectedDiscount to null
setRunningTotals([]); // Reset the running total
const soldLogs = syrupToppings
.filter((topping) => topping.isActive && !topping.custom)
.map((topping) => {
return {
name: topping.name,
price: topping.price,
isActive: topping.isActive,
soldCount: topping.soldCount + 1
};
});
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(soldLogs)
};
try {
const response = await fetch('http://localhost:5000/inventory', requestOptions);
if (response.ok) {
// Sold logs successfully updated in the inventory
console.log('Sold logs updated in the inventory.');
} else {
console.error('Failed to update sold logs in the inventory.');
}
} catch (error) {
console.error('Error occurred while updating sold logs in the inventory:', error);
}
// Send the relevant information to the simulated payment API
const paymentData = {
subtotal: originalTotal.toFixed(2),
tax: tax,
total: totalWithTax,
discount: selectedDiscount ? true : false,
discountAmount: discountAmount.toFixed(2),
discountType: discountType,
employee: loginNumberTracking,
};
try {
const paymentResponse = await fetch('http://localhost:5000/pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(paymentData)
});
if (paymentResponse.ok) {
const paymentResult = await paymentResponse.text();
console.log('Payment API response:', paymentResult);
if (!selectedDiscount) {
alert(`Please Present Payment\nSubtotal: ${originalTotal.toFixed(2)}\nTax: ${tax}\nTotal: ${totalWithTax}`);
} else {
alert(`Please Present Payment\nSubtotal: $${originalTotal.toFixed(2)}\nDiscount Amount: $${discountAmount.toFixed(2)}\nDiscount Type: ${discountType}\nTax: $${tax}\nTotal (after discount and tax): $${(originalTotal + parseFloat(tax)).toFixed(2)}`);
}
} else {
console.error('Failed to send payment data to the API.');
}
} catch (error) {
console.error('Error occurred while sending payment data to the API:', error);
}
};
const handleSelectDiscount = (discount) => {
if (selectedDiscount === discount) {
setSelectedDiscount(null); // Deselect the currently selected discount
} else {
setSelectedDiscount(discount); // Select the clicked discount
}
};
一般来说,StackOverflow 对我来说是最后的手段。如果我在这里的话,我至少已经呆了好几个小时了。我需要一个比我懂得更多的人;我的知识不足以解决这个问题。
最佳答案
正如错误消息所示:
Cannot read properties of undefined (reading 'toFixed')
发生错误是因为您尝试调用 toFixed()
undefined
的方法变量。
根据您提供的信息,很难正确判断是哪个部分导致了问题,但它可能是从 subtotal
发生的。没有被初始化和使用。
这些行:
// Reset the subtotal
setSubtotal(0);
let originalTotal = subtotal;
React 状态 setter 是异步的,因此如果您的小计是 undefined
当你运行setSubtotal(0)
时,仍然是undefined
运行后,直到下一个刻度之后,这意味着 originalTotal
也将是undefined
从而通过调用 originalTotal.toFixed(2)
导致错误.
如果不是这种情况,则可能是其他语句导致的。
关于javascript - ReactJS 函数与 toFixed 不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76715631/