Как отобразить динамические данные на круговой диаграмме с помощью иглы
Я пытаюсь построить круговую диаграмму с иглой и перезарядками. Связь . На самом деле я выбираю имя штата из раскрывающегося списка и хочу отобразить данные о энергопотреблении выбранного состояния на круговой диаграмме с помощью стрелки. Итак, вот мой файл States.json:
[
{
"state_id": "1",
"sortname": "AF",
"state_name": "ANDAMAN & NICOBAR ISLANDS",
"energyData": [
{
"data_id": "1",
"data": "367.3948635",
"state_id": "1"
}
]
},
{
"state_id": "2",
"sortname": "DZ",
"state_name": "ANDHRA PRADESH",
"energyData": [
{
"data_id": "2",
"data": "328.8017687",
"state_id": "2"
}
]
},
{
"state_id": "3",
"sortname": "AS",
"state_name": "ARUNACHAL PRADESH",
"energyData": [
{
"data_id": "3",
"data": "120.9100817",
"state_id": "3"
}
]
},
{
"state_id": "4",
"sortname": "AD",
"state_name": "ASSAM",
"energyData": [
{
"data_id": "4",
"data": "105.9831799",
"state_id": "4"
}
]
},
{
"state_id": "5",
"sortname": "AO",
"state_name": "CHANDIGARH",
"energyData": [
{
"data_id": "5",
"data": "564.5855402",
"state_id": "5"
}
]
},
{
"state_id": "6",
"sortname": "AI",
"state_name": "BIHAR",
"energyData": [
{
"data_id": "6",
"data": "118.696485",
"state_id": "6"
}
]
},
{
"state_id": "7",
"sortname": "AQ",
"state_name": "CHHATTISGARH",
"energyData": [
{
"data_id": "7",
"data": "213.6288618",
"state_id": "7"
}
]
},
{
"state_id": "8",
"sortname": "AG",
"state_name": "DADRA & NAGAR HAVELI",
"energyData": [
{
"data_id": "7",
"data": "213.6288618",
"state_id": "8"
}
]
},
{
"state_id": "9",
"sortname": "AR",
"state_name": "DAMAN & DIU ",
"energyData": [
{
"data_id": "7",
"data": "213.6288618",
"state_id": "9"
}
]
},
{
"state_id": "10",
"sortname": "AM",
"state_name": "GOA",
"energyData": [
{
"data_id": "7",
"data": "213.6288618",
"state_id": "10"
}
]
}
]
А вот моя страница расчетов, где находится раскрывающийся список:
import React, { useState } from 'react';
import LetsGoButton from './LetsGoButton';
import statesData from '../../public/states.json'
import Meter from './Meter';
const Calculation = () => {
const [statesId, setStatesId] = useState('')
const [avgConsumptionData, setAvgConsumptionData] = useState([])
const [conDataId, setConDataId] = useState('')
const handleStates = (e) => {
const getStateId = e.target.value
const getAvgEnergyData = statesData.find(state => state.state_id === getStateId)?.energyData
setAvgConsumptionData(getAvgEnergyData)
setStatesId(getStateId)
}
const handleAvgConsumptionData = (e) => {
const conDataId = e.target.value
console.log(conDataId);
setConDataId(conDataId)
}
return (
<section>
<div>
<div>
{/* STATE */}
<div>
<select defaultValue="State" name="state" id="state" onChange={(e) => handleStates(e)}>
<option selected disabled>State</option>
{
statesData.map((data, idx) => (
<option value={data.state_id} key={idx}>{data.state_name}</option>
))
}
</select>
</div>
<Meter conData={avgConsumptionData} />
</div>
<LetsGoButton />
</div>
</section>
);
};
export default Calculation;
Я передал avgConsumptionData компоненту Meter и попытался динамически установить данные в значении иглы. Вот компонент Meter:
import React, { useState } from 'react';
import { PieChart, Pie, Cell } from 'recharts';
const Meter = ({ conData}) => {
console.log(conData);
const RADIAN = Math.PI / 180;
const data = [
{ name: '0', value: 0, color: '#ff0000' },
{ name: '150', value: 150, color: '#00ff00' },
{ name: '300', value: 300, color: '#0000ff' },
{ name: '450', value: 450, color: '#924f64' },
{ name: '600', value: 600, color: '#dc8965' },
{ name: '750', value: 750, color: '#d2e1f7' },
{ name: '900', value: 900, color: '#131b27' },
];
const cx = 150;
const cy = 200;
const iR = 50;
const oR = 100;
const value = conData
// const value = conData[0].data
// const value = conData.map(x => x.data)
const needle = (value, data, cx, cy, iR, oR, color) => {
let total = 0;
data.forEach((v) => {
total += v.value;
});
const ang = 180.0 * (1 - value / total);
const length = (iR + 2 * oR) / 3;
const sin = Math.sin(-RADIAN * ang);
const cos = Math.cos(-RADIAN * ang);
const r = 5;
const x0 = cx + 5;
const y0 = cy + 5;
const xba = x0 + r * sin;
const yba = y0 - r * cos;
const xbb = x0 - r * sin;
const ybb = y0 + r * cos;
const xp = x0 + length * cos;
const yp = y0 + length * sin;
return [
<circle cx={x0} cy={y0} r={r} fill={color} stroke="none" />,
<path d={`M${xba} ${yba}L${xbb} ${ybb} L${xp} ${yp} L${xba} ${yba}`} stroke="#none" />,
];
};
return (
<div>
<PieChart>
<Pie
dataKey="value"
startAngle={180}
endAngle={0}
data={data}
cx={cx}
cy={cy}
innerRadius={iR}
outerRadius={oR}
fill="#8884d8"
stroke="none"
>
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
{needle(value, data, cx, cy, iR, oR, '#d0d000')}
</PieChart>
</div>
);
};
export default Meter;
Поэтому, когда я регистрирую переменную «value», которая содержит conData, содержащую данные выбранных состояний, я вижу в консоли массив, содержащий data_id, data и state_id. Но когда я хочу сопоставить массив, возникает ошибка:
Ошибка типа: невозможно прочитать свойства неопределенного значения (чтение «карты»)
почему возникает эта ошибка? Правильный или неправильный метод передачи данных из компонента расчета в компонент «Счетчик»? есть ли другой способ решить эту проблему?
1 ответ
Я только что изменил тип данных, который вы передавали в свой компонент Meter, с Array на Object.
Расчет.js
const handleStates = (e) => {
const getStateId = e.target.value
const getAvgEnergyData = statesData.find(state => state.state_id === getStateId)?.energyData
setAvgConsumptionData(getAvgEnergyData[0])
setStatesId(getStateId)
}
Метр.js
const Meter = ({ conData}) => {
console.log(conData);
const RADIAN = Math.PI / 180;
const data = [
{ name: '0', value: 0, color: '#ff0000' },
{ name: '150', value: 150, color: '#00ff00' },
{ name: '300', value: 300, color: '#0000ff' },
{ name: '450', value: 450, color: '#924f64' },
{ name: '600', value: 600, color: '#dc8965' },
{ name: '750', value: 750, color: '#d2e1f7' },
{ name: '900', value: 900, color: '#131b27' },
];
const cx = 150;
const cy = 200;
const iR = 50;
const oR = 100;
const value = conData.data
// const value = conData[0].data
// const value = conData.map(x => x.data)
const needle = (value, data, cx, cy, iR, oR, color) => {
let total = 0;
data.forEach((v) => {
total += v.value;
});
const ang = 180.0 * (1 - value / total);
const length = (iR + 2 * oR) / 3;
const sin = Math.sin(-RADIAN * ang);
const cos = Math.cos(-RADIAN * ang);
const r = 5;
const x0 = cx + 5;
const y0 = cy + 5;
const xba = x0 + r * sin;
const yba = y0 - r * cos;
const xbb = x0 - r * sin;
const ybb = y0 + r * cos;
const xp = x0 + length * cos;
const yp = y0 + length * sin;
return [
<circle cx={x0} cy={y0} r={r} fill={color} stroke="none" />,
<path d={`M${xba} ${yba}L${xbb} ${ybb} L${xp} ${yp} L${xba} ${yba}`} stroke="#none" />,
];
};
return (
<div>
<PieChart width={400} height={500}>
<Pie
dataKey="value"
startAngle={180}
endAngle={0}
data={data}
cx={cx}
cy={cy}
innerRadius={iR}
outerRadius={oR}
fill="#8884d8"
stroke="none"
>
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
{needle(value, data, cx, cy, iR, oR, '#d0d000')}
</PieChart>
</div>
);
};
export default Meter;
Вы можете просто получить атрибут данных из объекта с помощью conData.data . Также не забудьте добавить атрибуты ширины и высоты в вашу круговую диаграмму.
<PieChart width={400} height={500}>