How to load data dynamically with recharts correctly? - reactjs

Problem:
I am creating a react application. There I am using recharts to draw a bar chart. But It is not drawing for the data set which is dynamically loaded.
My code is like this.
import React from "react";
import {
BarChart,
Bar,
Cell,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
} from "recharts";
let data = [];
let item;
const data1 = [
{
id: 'Page A', count: 2400,
},
{
id: 'Page B', count: 2210,
},
{
id: 'Page C', count: 2290,
},
{
id: 'Page D', count: 2000,
},
{
id: 'Page E', count: 2181,
},
{
id: 'Page F', count: 2500,
},
{
id: 'Page G', count: 2100,
},
];
const addItemToData = (el) => {
item = {
id: el.id,
count: 2,
};
data.push(item);
};
const OffenceStatusChart = ({ offences }) => {
if (Object.keys(offences) !== 0) {
Object.values(offences).map((el, index) =>
addItemToData(Object.values(el)[1])
);
}
if (data1) {
console.log(data1);
console.log(data)
}
return (
<React.Fragment>
{data? (<BarChart
width={800}
height={300}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="id" />
<YAxis />
<Tooltip />
<Legend />
<Bar dataKey="count" fill="#8884d8" />
</BarChart>):null}
</React.Fragment>
);
};
export default OffenceStatusChart;
In here data1 array data set is working correctly but for data array data set it showing the chart as like this.
when I hover over the graph it shows like this.
In the inspect window is showing like this.
the data array is like this.
the data1 array is like this.
Both arrays are in same format but for the data array it is not drawing the bar char but for data1 array. I tried to realize so much what is this error but I was completely helpless so that is why I asked it here. So if someone can help me to solve this issue it really really grateful. Thank you

Related

How can I use a custom layer for each bar using a nivochart

I would like to be able to provide a custom layer on each of my bars in a Nivo responsive bar chart. I have been using this guide as a reference. I am creating a warning level and would like to have a line representing that level set on each bar. The issue I have is that the level is moving around when resizing the page.
The expected response upon screen resizing is for the warning level line to retain its expected position on the chart. What I am getting instead is the warning line moving from its desired position.
"next": "~12.2.4",
"#nivo/bar": "~0.79.1",
"#nivo/core": "~0.78.0",
My chart component using mock data -
import CardComponent from '#components/CardComponent';
import NivoWrapper from '#components/NivoWrapper';
import {
ResponsiveBar,
} from '#nivo/bar';
import React from 'react';
const data = [
{
x: '0',
name: 'weight5',
current: 200,
warningLevel: 100,
},
{
x: '1',
name: 'weight2',
current: 300,
warningLevel: 150,
},
{
x: '2',
name: 'weight3',
current: 400,
warningLevel: 200,
},
{
x: '3',
name: 'weight4',
current: 500,
warningLevel: 250,
},
{
x: '4',
name: 'weight5',
current: 600,
warningLevel: 300,
},
];
const MarginTop = 0;
const Marginright = 24;
const Marginbottom = 24;
const Marginleft = 64;
function Line({ bars, xScale }) {
return (
{bars.map((bar: any) => {
return (
<line
key={bar.key}
y1={bar.absY}
y2={bar.absY + bar.height}
x1={xScale(bar.width - bar.data.data.warningLevel - bar.data.data.warningLevel)}
x2={xScale(bar.width - bar.data.data.warningLevel - bar.data.data.warningLevel)}
stroke="black"
/>
);
})}
);
}
function PackageStockLevelChart() {
return (
<NivoWrapper>
<ResponsiveBar
data={data}
indexBy="name"
keys={['current']}
layout="horizontal"
enableLabel={false}
axisLeft={{
tickValues: 7,
}}
margin={{
top: MarginTop, right: Marginright, bottom: Marginbottom, left: Marginleft,
}}
enableGridY={false}
colors="green"
legendLabel="legend label"
legends={[{
dataFrom: 'keys',
anchor: 'bottom-right',
direction: 'column',
itemWidth: 80,
itemHeight: 16,
translateY: -16,
}]}
layers={['axes', 'bars', Line, 'legends']}
/>
</NivoWrapper>
);
}
export default PackageStockLevelChart;
View before resizing -
View before resizing
During / After resizing
View during after reszing

Function does not work on first render instead the series is generated after the subsequent renders

My function generateSeriesDataWithColor() seems like it does not load before the component or page renders.
So, the seriesWithColor should get the data genrated by generateSeriesDataWithColor() right away when the component is loaded but it does not get generated at the first render, instead if the component is rendered again, the colors and the graph shows up.
import HighchartsReact from "highcharts-react-official";
import Highcharts from "highcharts";
import './SkillsGraph.scss';
import { Col, Row } from "react-bootstrap";
import HeadingMain from "../../Heading/HeadingMain/HeadingMain";
export default function SkillsGraph(){
const skills = ['HTML5/CSS3/JS', 'Java11', 'PHP', 'MySql', 'MongoDB', 'ReactJS', 'ExpressJS'];
const series = {
name: 'Skill Level',
data: [ 10, 9.5, 7, 9.5, 8, 8.5, 8]
};
const seriesWithColor = generateSeriesDataWithColor(series); // This is where the series is assigned to the var
// Randomly generate colors
function generateRandomColor(){
let maxVal = 0xFFFFFF; // 16777215
let randomNumber = Math.random() * maxVal;
randomNumber = Math.floor(randomNumber);
randomNumber = randomNumber.toString(16);
let randColor = randomNumber.padStart(6, 0);
return `#${randColor.toUpperCase()}`
}
// Generate the data with random conlor
function generateSeriesDataWithColor(seriesData){
const data = seriesData.data;
const dataArray = data.map((item) => {
let color = generateRandomColor();
while(color === "#FFFFFF"){
color = generateRandomColor();
}
let dataObj = {
y: item,
color: color
}
return dataObj;
})
let seriesWithColor = {
name: 'Skill Level',
data: dataArray
}
return seriesWithColor; //This is from where the data/series is returned
}
// Options for the graph
let options = {
chart: {
type: 'bar',
height: 400
},
title: {
align: 'left',
text: 'Skills represented'
},
xAxis: {
categories: skills,
visible: true,
type: 'Skills categorised',
title: {
text: null
}
},
yAxis: {
min: 0,
max: 10,
title: {
text: 'Skill Level',
align: 'high'
},
labels: {
overflow: 'justify'
}
},
plotOptions: {
bar: {
dataLabels: {
enabled: false
}
},
column: {
colorByPoint: true
}
},
colors: [
'#ff0000',
'#00ff00',
'#0000ff',
'#0000ff',
'#0000ff',
'#0000ff',
'#0000ff'
],
legend: {
enabled: true
},
credits: {
enabled: false
},
series: seriesWithColor // This is where the generated data/series is used
}
return (
<Row>
<Col md={3}>
<HeadingMain name="This is Legend"></HeadingMain>
</Col>
<Col md={9}>
<HighchartsReact highcharts={Highcharts} options={options} className="chart"></HighchartsReact>
</Col>
</Row>
)
}
Does anyone have a solution for this?
I tried using useEffect hook to complete the wanted task but it gives an error message - 'React Hook useEffect has missing dependencies: 'generateSeriesDataWithColor' and 'series'. Either include them or remove the dependency array react-hooks/exhaustive-deps'. (Please check the code below)
const [seriesWithColor, setSeries] = useState(null);
useEffect(() => {
generateSeriesDataWithColor(series)
.then(data => setSeries(data))
.catch(err => console.log(err));
}, []);
Series needs to be an array of objects instead of a single object:
let options = {
...,
series: [seriesWithColor] // This is where the generated data/series is used
};
Live demo: https://codesandbox.io/s/highcharts-react-demo-h4r493?file=/demo.jsx
API Reference: https://api.highcharts.com/highcharts/series
You will need to call the function within useEffect hook to make sure that the data is available.

Get the Multi-column filter condition data from MUI datagrid table

I want to get the filtered data from MUI DataGrid Table and want to send it to backend
Please suggest how should I save the filter condition data .
export default function MultiFilteringGrid() {
const { data } = useDemoData({
dataSet: 'Commodity',
rowLength: 200,
maxColumns: 6,
});
const [filterModel, setFilterModel] = React.useState({
items: [
{ id: 1, columnField: 'commodity', operatorValue: 'contains', value: 'rice' },
{ id: 2, columnField: 'quantity', operatorValue: '>=', value: '20000' },
],
});
return (
<div style={{ height: 400, width: '100%' }}>
<DataGridPro
{...data}
filterModel={filterModel}
onFilterModelChange={(model) => setFilterModel(model)}
/>
</div>
);
}

Recharts - How to fix graph scaling issue?

In React application (using Next.js), I am trying to implement graph feature using recharts http://recharts.org/en-US/api/LineChart. My code is as below,
/index.js
const formatDate = (value) => {
return moment.unix(value).format('HH:MM A DD MM, YYYY')
}
const weeklyData = [
{ date: formatDate(1613619000), price: '1200.00' },
{ date: formatDate(1613617200), price: '1300.83' },
{ date: formatDate(1613615400), price: '1250.23' },
{ date: formatDate(1613611800), price: '500.55' },
{ date: formatDate(1613608200), price: '1600.23' },
{ date: formatDate(1613606400), price: '1850.93' },
{ date: formatDate(1613604600), price: '1750.23' },
{ date: formatDate(1613599200), price: '650.23' },
]
<LineChart
width={900}
height={250}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<Tooltip content={<CustomTooltip />} cursor={false} />
<Line type="monotone" dataKey="price" stroke="#4ec6f4" label="Shruthi" />
</LineChart>
/tooltip.js
const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="tooltip">
<p className="tooltipLabel">{`$${payload[0].payload?.price}`}</p>
<p className="tooltipDesc">{`${payload[0]?.payload?.date}`}</p>
</div>
)
}
return null
}
CustomTooltip.propTypes = {
type: PropTypes.string,
payload: PropTypes.array,
label: PropTypes.string,
}
export default CustomTooltip
Right now YAxis is restricted to 1000 and graph(scaling) is displaying out of the box and its invisible.
Graph should be display within the container which I have set.
Here price is not fixed, it can be like 123456.88 or more than this.
In all scenario, how can I fix this issue?
try to convert price type to number or use values without single quotes.
Note: if possible, Post complete code for better response

Pie Chart Label is not visible in ReactJS

I am trying to create a Pie Chart dashboard. Chart is getting drawn based on the value, but the legend is not getting displayed. I have tried the label as below.
Chart
Summary.js:
import React, { Component } from 'react';
import PieChart from 'react-minimal-pie-chart';
class Summary extends Component {
render()
{
return(
<PieChart className="chart-style" x={50} y={60} outerRadius={100} innerRadius={50}
data={[
{ value: 11, color: '#E38627',label: 'New' },
{ value: 12, color: '#C13C37',label: 'Closed' },
{ value: 8, color: '#6A2135',label: 'Reopened' },
]}
/>
);
}
}
export default Summary;
Adding this works for me.
label={(props) => { return props.dataEntry.title;}}
Example
<PieChart
label={(props) => { return props.dataEntry.title;}}
data={[{ title: "One", value: 10, color: "#E38627" },
{ title: "Two", value: 15, color: "#C13C37" },
{ title: "Three", value: 20, color: "#6A2135" },
]}
/>
Its works at least for display labels, but you can customize it for showing percentage as well.
A good way to solve it is to provide a label function
<PieChart ...
label={props => { return props.data[props.dataIndex].label;}}
/>
You can also just provide label={true} but then it will show te value not the label in the data array.

Resources