React UI无法展示后端API返回数据的问题排查与解决
问题排查与解决:React UI无法展示API返回的数据
问题背景
开发的React应用通过POST请求调用后端API处理图片,后端返回预期JSON数据,但UI无法展示提取结果,控制台无报错信息。
React组件代码
import React, { useState } from "react"; import axios from "axios"; import { useDropzone } from "react-dropzone"; interface ExtractedData { company: string; invoice_date: string; items: { description: string; quantity: number; amount: string }[]; // Changed amount to string for "$745.00" format total_amount: string; practitioner: string; patient: string; location: string; currency: string | null; other_details?: string; } const ImageUploadOCR: React.FC = () => { const [image, setImage] = useState<File | null>(null); const [data, setData] = useState<ExtractedData | null>(null); const [loading, setLoading] = useState<boolean>(false); const { getRootProps, getInputProps } = useDropzone({ accept: { "image/*": [] }, onDrop: (acceptedFiles) => setImage(acceptedFiles[0]), }); const handleUpload = async () => { if (!image) return; setLoading(true); const formData = new FormData(); formData.append("image", image); try { console.log("Data disk reached"); const response = await axios.post("http://localhost:5000/api/extract", formData, { headers: { "Content-Type": "multipart/form-data" }, }); // Log the full response to verify the structure console.log("Response data:", response.data); // Set data to the state setData(response.data); // Optionally log company and invoice_date for debugging console.log("Company:", response.data?.company); console.log("Invoice Date:", response.data?.invoice_date); } catch (error) { console.error("Error uploading image:", error); } finally { setLoading(false); } }; return ( <div className="p-6 max-w-2xl mx-auto"> <div {...getRootProps()} className="border-2 border-dashed p-4 cursor-pointer text-center"> <input {...getInputProps()} /> {image ? <p><img src={URL.createObjectURL(image)} /></p> : <p>Drag & drop an image, or click to select</p>} </div> <button className="mt-4 bg-blue-500 text-white px-4 py-2 rounded" onClick={handleUpload} disabled={!image || loading}> {loading ? "Processing..." : "Upload & Extract"} </button> {data && ( <div className="mt-6"> <h2 className="text-xl font-bold mb-2">Extracted Data</h2> <table className="w-full border-collapse border border-gray-300"> <thead> <tr> <th className="border p-2">Field</th> <th className="border p-2">Value</th> </tr> </thead> <tbody> <tr> <td className="border p-2">Company</td> <td className="border p-2">{data?.company || "Not available"}</td> {/* Optional chaining added */} </tr> <tr> <td className="border p-2">Invoice Date</td> <td className="border p-2">{data?.invoice_date || "Not available"}</td> {/* Optional chaining added */} </tr> </tbody> </table> <h3 className="text-lg font-bold mt-4">Items</h3> <table className="w-full border-collapse border border-gray-300"> <thead> <tr> <th className="border p-2">Description</th> <th className="border p-2">Quantity</th> <th className="border p-2">Amount</th> </tr> </thead> <tbody> {data.items.map((item, index) => ( <tr key={index}> <td className="border p-2">{item.description}</td> <td className="border p-2">{item.quantity}</td> <td className="border p-2">{item.amount}</td> </tr> ))} </tbody> </table> </div> )} </div> ); }; export default ImageUploadOCR;
后端返回的JSON数据
{ "Currency": null, "Location": "102 Trope Street, New York, NY 45568", "Other relevant details": { "Due date": "07/30/23", "Invoice number": "12245", "Note": "A prescription has been written out for patient, for an acute throat infection.", "Subtotal": "$745.00", "Tax amount": "$157.05", "Tax rate": "9%" }, "Patient": "Kemba Harris", "Practitioner": "Dr. Alanah Gomez", "Total Amount": "$1,902.05", "company": "Not specified", "invoice_date": "07/01/23", "items": [ { "Amount": "$745.00", "Description": "Full Check Up", "Quantity": "1" }, { "Amount": "$1,000.00", "Description": "Ear & Throat Examination", "Quantity": "1" } ] }
问题原因
核心问题是后端返回的字段名、结构与前端TypeScript接口定义不匹配,导致React组件无法正确读取数据:
- 字段大小写不匹配:
- 后端返回
Location、Patient、Practitioner、Currency,但前端接口定义的是location、patient、practitioner、currency - 后端返回
Total Amount,前端接口是total_amount;后端Other relevant details对应前端other_details
- 后端返回
- items数组字段不匹配:
- 后端items里的字段是
Amount、Description、Quantity,但前端接口里是amount、description、quantity
- 后端items里的字段是
- 类型不匹配:
- 前端把
quantity定义为number类型,但后端返回的是字符串格式(如"1")
- 前端把
解决方法
推荐在前端处理API响应时,做字段映射与类型转换,避免修改后端接口。修改handleUpload函数中的数据处理逻辑:
// 替换原setData(response.data)的代码 const mappedData: ExtractedData = { company: response.data.company || "Not available", invoice_date: response.data.invoice_date || "Not available", total_amount: response.data["Total Amount"] || "Not available", practitioner: response.data.Practitioner || "Not available", patient: response.data.Patient || "Not available", location: response.data.Location || "Not available", currency: response.data.Currency, other_details: JSON.stringify(response.data["Other relevant details"]) || undefined, items: response.data.items.map(item => ({ description: item.Description || "", quantity: parseInt(item.Quantity) || 0, // 转换为number类型 amount: item.Amount || "" })) }; setData(mappedData);
同时,为了让UI展示更多字段,可以更新渲染部分的表格,添加缺失的字段:
// 在Extracted Data表格的tbody中添加以下行 <tr> <td className="border p-2">Practitioner</td> <td className="border p-2">{data?.practitioner || "Not available"}</td> </tr> <tr> <td className="border p-2">Patient</td> <td className="border p-2">{data?.patient || "Not available"}</td> </tr> <tr> <td className="border p-2">Location</td> <td className="border p-2">{data?.location || "Not available"}</td> </tr> <tr> <td className="border p-2">Total Amount</td> <td className="border p-2">{data?.total_amount || "Not available"}</td> </tr> <tr> <td className="border p-2">Other Details</td> <td className="border p-2">{data?.other_details || "Not available"}</td> </tr>
验证
修改后,重新上传图片,控制台打印的mappedData会完全匹配前端接口定义,UI就能正确展示所有提取的数据。
内容的提问来源于stack exchange,提问作者GoneCase123
相关产品推荐
相关产品推荐

