Recharts: No display when looping twice inside the BarChart - reactjs

I use Recharts to display my charts.
My data looks like that:
const data = [
{name: 'day 1', supermarket1:{strawberry:4090, apple:3740} , supermarket2:{strawberry:6498, apple:1008}, supermarket3:{strawberry:4090, apple:3740}},
{name: 'day 2', supermarket1:{strawberry:200, apple:768} , supermarket2:{strawberry:700, apple:876}, supermarket3:{strawberry:300, apple:932}}
]
I want to loop twice inside the barchart to display my data
I tried with just one loop inside the barchart and it worked perfectly but when I want to loop twice the display doesn't appear I don't know why
My code looks like that:
const SimpleBarChart = React.createClass({
render () {
return (
<BarChart width={600} height={300} data={data}
margin={{top: 5, right: 30, left: 20, bottom: 5}}>
<CartesianGrid strokeDasharray="3 3"/>
<XAxis dataKey="name"/>
<YAxis/>
{["supermarket1", "supermarket2", "supermarket3"].map((elt, index) =>{
["strawberry", "apple"].map((fruit, index2) =>{
console.log(`${elt}.${fruit}`);
return(
<Bar
key={index + index2}
dataKey={`${elt}.${fruit}`}
fill="#1f77b4"
>
</Bar>
)
})
})}
</BarChart>
);
}
})

The solution is to map twice outside the BarChart and organize the data as wished in a third array to use it inside the BarChart.
const SimpleBarChart = React.createClass({
render () {
let keys= [];
{["supermarket1", "supermarket2", "supermarket3"].map((elt, index) =>{
["strawberry", "apple"].map((fruit, index2) =>{
keys.push(`${elt}.${fruit}`)
})
})}
return (
<BarChart width={600} height={300} data={data}
margin={{top: 5, right: 30, left: 20, bottom: 5}}>
<CartesianGrid strokeDasharray="3 3"/>
<XAxis dataKey="name"/>
<YAxis/>
{keys.map((key, index) =>{
return(
<Bar
key={index}
dataKey={`${key}`}
fill="#1f77b4"
></Bar>
)
})}
</BarChart>
);
}
})
demo

Related

How to show the percentage after the bar chart in react recharts?

I want to show this percentage after the bar chart. I have made this with react recharts
Check photo
<BarChart
width={window.innerWidth < 900 ? 280 : 380}
height={200}
data={data}
margin={{ top: 20, right: 30, left: 20, bottom: 5 }}
layout='vertical'
>
{/* <CartesianGrid strokeDasharray="3 3" /> */}
<XAxis type='number' tick={false} axisLine={false} />
<YAxis type='category' dataKey='name' width={window.innerWidth < 900 ? 110 : 120}
stroke="#fff" style={{ fontSize: '14px' }} />
<Bar dataKey="pv" stackId="a" fill="#4EDCF0" />
</BarChart>
You can use cutom tooltips to write your own logic to show percentage
Working example if u want to take a look - https://codesandbox.io/s/epic-cache-kx8ze2?file=/src/App.js
<BarChart
width={500}
height={300}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip content={<CustomTooltip />} />
<Legend />
<Bar dataKey="amt" barSize={20} fill="#8884d8" />
</BarChart>
Custom tooltip
const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p className="label">{`${label} : ${payload[0].value}`}</p>
<p> percentage : {percentage (payload)}</p>
</div>
);
}
return null;
};
the function to calculate the percentage
const percentage = (data)=>{
console.log(data[0].value);
const total = 10000
const calcualtion = (data[0].value/total) * 100 // total to be replaced by the totla value
return calcualtion
}
hope it helps

Is it possible to sync between Line Chart and Scattered Chart in Recharts?

I have a scattered and a line chart type. I am trying to sync between these charts type.
I have these problems:
the tooltip does not appear in scattered chart when I hover to line chart, but the "cursor line" sync
when I hover in the scattered chart, there is no sync between line and scattered chart
the details can be seen here:
here is the code I have
const Chart = ({ type, matrixData, index, diagcodeLabel }) => {
const getMinValue = Math.min(...matrixData.map((data) => data[type]));
const getMaxValue = Math.max(...matrixData.map((data) => data[type]));
return (
<div className="chart">
<div className="title">{type}</div>
<ResponsiveContainer key={"responsiveInformation"} width="100%" height={170}>
{type === "DIAGCODE" ? (
<ScatterChart
syncId="chart"
width={1200}
height={400}
margin={{
top: 20,
right: 20,
bottom: 20,
left: 20,
}}
>
<YAxis
type="number"
dataKey="dLevel"
tickFormatter={(value) => {
return Object.keys(diagcodeLabel).find((k) => diagcodeLabel[k] === value);
}}
/>
<Tooltip />
<CartesianGrid strokeDasharray="3 3" className="chartGrid" />
<Legend layout="vertical" content={<CustomLegend />} />
<Scatter name="DiagCode" data={matrixData} fill="#8884d8" shape={"circle"}>
{matrixData.map((entry, index) => {
return (
<Cell
key={"cell-${index}"}
fill={entry.IsLockout === "Lockout" ? "#5fb0ff" : "rgb(172, 45, 45)"}
/>
);
})}
</Scatter>
</ScatterChart>
) : (
<LineChart
syncId="chart"
width={500}
height={50}
data={matrixData}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" className="chartGrid" />
<YAxis dataKey={type} domain={[getMinValue, getMaxValue]} />
<Tooltip />
<Line type="monotone" dataKey={type} stroke="#8884d8" activeDot={{ r: 8 }} />
</LineChart>
)}
</ResponsiveContainer>
</div>
);};
Is there a way I could sync them ?
I think this kind of feature is underdevelopment https://github.com/recharts/recharts/issues/1541
So, I ended up using composed charts (Scattered and Bar) https://recharts.org/en-US/examples/LineBarAreaComposedChart and I set the fillOpacity transparent for Bar. but I am not sure if it is the best workaround...

Recharts set Y-axis to YES and NO

What code changes would I need to make to replace 1 with YES and 0 with NO?
It seems like it should be possible from the examples on http://recharts.org/ or just finding it from a general search, however I haven't found anything that resolves this.
The only part of the code that is I didn't post here are the imports at the top of the file.
Here is the graph
const data = [
{yl: "YES",name: "p1",'X axis': 1,},
{yl: "YES",name: "p2",'X axis': 1,},
{yl: "NO" ,name: "p3",'X axis': 0,},
];
export const esChart: React.FC = () => {
return (
<LineChart
width={500}
height={300}
data={data}
margin={{
top: 100,
right: 30,
left: 20,
bottom: 5
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis tickCount={1} />
<Tooltip />
<Legend />
<Line
type="monotone"
dataKey='X axis'
stroke="#8884d8"
activeDot={{ r: 8 }}
/>
</LineChart>
);
}
export default esChart;
You need to add tickFormatter prop to customize the same. (Working codesandbox)
<YAxis tickCount={1} tickFormatter={(...allArgs)=>{ console.log(allArgs) if(allArgs[0] ===0){ return "Y" }else{ return "N" } }}/>

Elements not showing up on React Native

Current Output:
Expected Output:
Current Code Implementation:
import React from 'react'
import { LineChart, XAxis, YAxis } from 'react-native-svg-charts'
import { View, Text } from 'react-native'
import { Line, Circle, G, Rect, } from 'react-native-svg'
export default class Chart extends React.PureComponent {
handleFill = (value) => {
if (value>100){
return "rgba(190, 30, 45, 0.5)"
}
else if (value>80 && value<=100){
return "yellow"
}
else{
return "#CCE6D0"
}
}
render() {
const data = [
...
];
const values = data.map(a => a.value);
const days = data.map(a => a.day);
const axesSvg = { fontSize: 10, fill: 'grey' };
const verticalContentInset = { top: 10, bottom: 10 }
const xAxisHeight = 30
const Decorator = ({x, y, data}) => {
return values.map((value, index) => (
<View>
<View style={{marginBottom:50}}>
<Rect
x={x(index)-1.75}
y={y(value+8)}
width="4"
height="40"
fill={this.handleFill(value)}
/>
</View>
<Circle
key={index}
cx={x(index)}
cy={y(value)}
r={2}
stroke={'#639123'}
fill={'#606060'}
/>
</View>
));
};
return (
<View>
<Text style={{fontSize:10}}>BPM</Text>
<View style={{ height: 200, flexDirection: 'row' }}>
<YAxis
...
/>
<View style={{ flex: 1, marginLeft: 10 }}>
<LineChart
...
>
<Decorator />
</LineChart>
<XAxis
....
/>
</View>
</View>
</View>
)
}
}
I am using the react-native-svg-charts library to render a line chart with custom handlers.
As seen in the code, the handler consists of a circle and a rect, which simply do not show up. Could this be a library version problem? I have updated both react-native-svg and react-native-svg-charts to the latest version. What am I missing? Any ideas?
I've gotten it to work like this:
import React from 'react';
import {LineChart, XAxis, YAxis} from 'react-native-svg-charts';
import {View, Text} from 'react-native';
import {Svg, Line, Circle, G, Rect} from 'react-native-svg';
export default class CustomLineChartOne extends React.PureComponent {
handleFill = (value) => {
if (value > 100) {
return 'rgba(190, 30, 45, 0.5)';
} else if (value > 80 && value <= 100) {
return 'yellow';
} else {
return '#CCE6D0';
}
};
render() {
const xAxisLabels = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
const data = [50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24];
const Decorator = ({x, y, data}) => {
return data.map((value, index) => (
<View>
<Rect
x={x(index) - 1.75}
y={y(value + 8)}
width="4"
height="40"
rx="2"
fill={this.handleFill(value)}
/>
<Circle
key={index}
cx={x(index)}
cy={y(value)}
r={2}
stroke={'#639123'}
fill={'#606060'}
/>
</View>
));
};
return (
<View
style={{
height: 200,
flexDirection: 'row',
padding: 20,
}}>
<YAxis
data={data}
contentInset={{top: 20, bottom: 20}}
svg={{
fill: 'black',
fontSize: 10,
}}
/>
<View style={{flex: 1}}>
<LineChart
style={{flex: 1}}
data={data}
svg={{stroke: 'rgb(134, 65, 244)'}}
contentInset={{top: 10, bottom: 10, left: 10, right: 10}}>
<Decorator />
</LineChart>
<XAxis
style={{marginHorizontal: -10}}
data={data}
formatLabel={(value, index) => xAxisLabels[index]}
contentInset={{left: 10, right: 10}}
svg={{fontSize: 10, fill: 'black'}}
/>
</View>
</View>
);
}
}
The important parts to look at here are how the data and xAxisLabels are defined, how the labels are formatted and how data is mapped over inside the decorator to create the bars and circles.
It's not entirely clear what the exact problem was with your code as you've left out some important parts, but I think the problem was mainly related to how you had set up your data.
The result looks like this:

Recharts line chart cut off top line

I am using recharts line chart it's working nicely but sometimes cut off top of the line.
Please check the snippet in jsfiddle.
const {LineChart, Line, XAxis, YAxis, ReferenceLine, CartesianGrid, Tooltip, Legend} = Recharts;
const data = [
{"Date":"16 May","Download":"40717"},{"Date":"17 May","Download":"39640"},{"Date":"18 May","Download":"52122"},{"Date":"19 May","Download":"51800"},{"Date":"20 May","Download":"49605"},{"Date":"21 May","Download":"45601"},{"Date":"22 May","Download":"43798"},{"Date":"23 May","Download":"36113"},{"Date":"24 May","Download":"278531"},{"Date":"25 May","Download":"323521"},{"Date":"26 May","Download":"154527"},{"Date":"27 May","Download":"119990"},{"Date":"28 May","Download":"100524"},{"Date":"29 May","Download":"83121"},{"Date":"30 May","Download":"60536"},{"Date":"31 May","Download":"58208"},{"Date":"01 Jun","Download":"304154"},{"Date":"02 Jun","Download":"538870"},{"Date":"03 Jun","Download":"213244"},{"Date":"04 Jun","Download":"130246"},{"Date":"05 Jun","Download":"104131"},{"Date":"06 Jun","Download":"72564"},{"Date":"07 Jun","Download":"69012"},{"Date":"08 Jun","Download":"96166"},{"Date":"09 Jun","Download":"89748"},{"Date":"10 Jun","Download":"80895"},{"Date":"11 Jun","Download":"155434"},{"Date":"12 Jun","Download":"81735"},{"Date":"13 Jun","Download":"56838"}
];
const SimpleLineChart = React.createClass({
render () {
return (
<LineChart width={600} height={300} data={data}
margin={{top: 0, right: 50, left: 20, bottom: 5}}>
<CartesianGrid strokeDasharray="3 3"/>
<XAxis dataKey="Date"/>
<YAxis/>
<Tooltip/>
<Legend />
<Line type="monotone" dataKey="Download" stroke="#8884d8" />
</LineChart>
);
}
})
ReactDOM.render(
<SimpleLineChart />,
document.getElementById('container')
);
https://jsfiddle.net/rafiul_fiddle/tp0zL5s1/
Issue :
The issue is due to "Download":"40717"
Solution :
convert download -> string to int
// data={data.map(d => ({...d , "Download" : +d.Download }))
<LineChart
width={600}
height={300}
data={data.map(d => ({...d , "Download" : +d.Download }))} // <---- HERE
margin={{top: 0, right: 50, left: 20, bottom: 5}}>
WORKING DEMO

Resources