Как отобразить динамические данные на круговой диаграмме с помощью иглы

Я пытаюсь построить круговую диаграмму с иглой и перезарядками. Связь . На самом деле я выбираю имя штата из раскрывающегося списка и хочу отобразить данные о энергопотреблении выбранного состояния на круговой диаграмме с помощью стрелки. Итак, вот мой файл 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}>
Другие вопросы по тегам