在react-chartjs-2中正确展示后端返回JSON数据为柱状图的实现问题
Let's break down what's going wrong with your current code and fix it step by step. The core problem is that you're creating a new dataset entry for every single data point, and each dataset's data array only has one value—no alignment to the correct constituency index. Here's how to adjust the logic to map counts to the right positions:
Step 1: Restructure the Data Mapping Logic
We need to:
- First collect all unique constituencies and create a lookup for their index in the labels array
- Initialize each candidate's dataset with zeros for every constituency
- Then fill in the actual counts based on the raw data
Here's the revised code:
const generateGraph = (data) => { // 1. Collect unique constituencies and create an ID-to-index lookup const constituencyMap = new Map(); const conArr = []; // First pass to get all unique constituencies from the data data.forEach(d => { if (!constituencyMap.has(d.constituencyId)) { const con = constituencies.find(c => c.constituencyId === d.constituencyId); if (con) { constituencyMap.set(d.constituencyId, conArr.length); conArr.push(con.name); } } }); // 2. Initialize datasets for each unique candidate, with 0s for all constituencies const candidateMap = new Map(); const canArr = []; data.forEach(d => { const can = candidates.find(c => c.candidateId === d.candidateId); if (!can) return; const candidateKey = can.candidateId; if (!candidateMap.has(candidateKey)) { // Create dataset with 0s matching the length of constituencies const newDataset = { label: `${can.lastName}, ${can.firstName}`, data: Array(conArr.length).fill(0) }; candidateMap.set(candidateKey, canArr.length); canArr.push(newDataset); } // 3. Fill in the actual count at the correct constituency index const constituencyIndex = constituencyMap.get(d.constituencyId); const datasetIndex = candidateMap.get(candidateKey); canArr[datasetIndex].data[constituencyIndex] = d.count; }); const chartData = { labels: conArr, datasets: canArr, }; return chartData; };
Why This Works
- Constituency Lookup: We use a
Mapto store each constituency ID's position in thelabelsarray. This lets us quickly find where to place a count for any given constituency. - Zero-Initialized Datasets: Each candidate's dataset starts with an array of zeros that matches the number of constituencies. This ensures every constituency has a value (even 0) for every candidate.
- Targeted Count Assignment: For each data point, we find the correct constituency index and candidate dataset, then replace the 0 with the actual count.
Example Output
Using your sample scenario where:
- Person 1 has a count of 1 in Constituency A
- Person 2 has a count of 1 in Constituency B
The generated chartData will be exactly what you need:
{ labels: ["A", "B"], datasets: [ { label: "Person 1", data: [1, 0] }, { label: "Person 2", data: [0, 1] } ] }
This will render correctly: Person 1's bar shows up in Constituency A, Person 2's bar shows up in Constituency B, and empty positions show 0 (no bar, or a bar with height 0 depending on your chart config).
内容的提问来源于stack exchange,提问作者user15187712

