I have this chart component which gets an address from its parent and it gets the chartData for that address from the hook useData. When a new address is passed in, the chart data does change but only the labels render for some reason. I'm wondering if there is a better way of doing this.
function Chart({ address }) {
const { labels, Data: chartData } = useData(address);
const data = (labels, chartData) => {
return {
labels: labels,
datasets: [
{
label: "Line 1",
data: chartData,
},
],
};
};
return <Bar id={address} data={data(labels, chartData)} redraw={true} />;
}
Related
I want to load an image for one of the data points in a Scatter chart. The problem I have is the image doesn’t load on the initial page/chart render. Image only appears when you click/interact with the chart.
I am using react-chartjs-2, any suggestions would be appreciated.
I’ve tried the following (snippet)
import { Scatter, Chart } from "react-chartjs-2";
const chartReference = useRef();
const myImage = new Image(25, 35);
myImage.src = '/img/myimage.svg';
const chartData = {
datasets: [{
label: 'my Image',
data: [{ x: dummyData, y: 25 }],
pointStyle: myImage,
radius: 1,
pointRadius: 10,
borderWidth: 0,
type: 'line',
}],
}
return (
<Scatter
height={height}
width={width}
data={chartData}
options={options}
plugins={[Zoom]}
ref={chartReference}
redraw={true}
/>
I also through of this but where should do I place this?
chartReference.current.chartInstance.data.datasets[0].pointStyle = myImage;
chartReference.current.chartInstance.update();
If you manage to solve that I would like to ask a part 2 question that is the when you pan the chart unlike the built in data pointStyle the image goes off the y-axis. It only hide when at the charts actual width
It should work if you define the Image inside the component constructor...
constructor() {
super();
const myImage = new Image(25, 35);
myImage.src = "/img/myimage.svg";
and create the Scatter chart inside the render method.
render() {
return (
<div>
<Scatter
data={this.state.chartData }
options={this.state.chartOptions}
...
/>
</div>
);
}
Please have a look at this StackBlitz.
let GraphProjection = props => {
let [chartData, setChartData] = useState({});
let val1=props.recover[0]
let date=props.recover[1]
// let temp=length(date)
//console.log('typ1 ', (temp));
let jj=['323','3223']
let chart = () => {
setChartData({
labels: date,
datasets: [
{
label: props.recover[3],
data: val1,
backgroundColor: ["rgba(75, 192, 192, 0.6)"],
borderWidth: 4
}
]
});}
useEffect(() => {
chart();
}, []);
return (
<div className="App">
<h1>{props.recover[2]}</h1>
<div style={{height:"700px" ,width:"1200px"}}>
<Line data={chartData} options={ {responsive :true}}/>
</div>
</div>
)
}
I am calling this component from other component
this.grapshow=( (<StatewiseGraphsec statecode ={this.x}/>))
For the first time it works but then it doesn't updates?? I think it is because of render issue.If I try to set state it's not allowing
Actually date is constant Inam changing the Val1 which is the y-axis.
So I am having a dropndown in a component which I use to filter values and send to this component for graph creation.It works for first selection only.
I'm trying to create a static (non-clickable) Pie chart using react-chartjs-2.
However I want one of the slices to "pop out", or appear bigger than the others:
Hence, I'm trying to access one of the slices in the pie chart and modify its outerRadius property.
I've encountered multiple similar questions both in Stack Overflow and in Github, which helped me come up with this:
import { Pie } from 'react-chartjs-2';
<Pie
data={data}
options={options}
getElementsAtEvent={(elems) => {
// Modify the size of the clicked slice
elems[0]['_model'].outerRadius = 100;
}}
/>
However I didn't find anything about getting a slice to pop out without the user clicking it.
After looking under Pie component's hood, I ended up finding the answer.You can find it inside componentDidMount():
import React, { Component } from 'react';
import { Pie } from 'react-chartjs-2';
class PieChart extends Component {
componentDidMount() {
const change = {
sliceIndex: 0,
newOuterRadius: 100
}
const meta = this.pie.props.data.datasets[0]._meta;
meta[Object.keys(meta)[0]]
.data[change.sliceIndex]
._model
.outerRadius = change.newOuterRadius;
}
render() {
const data = {
type: 'pie',
datasets: [ { data: [10, 20, 30] } ],
labels: ['a', 'b', 'c'],
};
const options = {};
return <Pie
ref={(self) => this.pie = self}
data={data}
options={options}
/>
}
}
export default PieChart;
I have one more solution with version 4.3.1.
Try to add offset property into datasets.
import { Pie } from 'react-chartjs-2';
<Pie
data={
datasets: [
{
data: [1, 1],
borderColor: ['black', 'transparent'],
offset: [10, 0],
},
],
}
/>
It will render Pie with 2 segments. For the first segment, you will have black border and 10px offset
I have a doughnut chart with static labels - what is changing, is only the data with values for labels. It's all about filtering data. But I have some weird issue and I can't figure out whats going on.
For example I've got something like this:
labels with hidden option set to true
I figure out that 'undefined' value in Array, makes item hidden so in case from picture it will be for example: [234, undefined, 21, undefined, 8].
Ok it's seems to be fine but when I use filter panel to change data in my application, and props with this Array of values is changing it's not rerendering label view, for example when I change array to [234, 100, 21, undefined, 8], label at position label1 should change 'hidden' property to false - it won't happening and I don't know why.
I paste here only render method, if u need to know something else please tell me:
render() {
const chartOptions = {
legend: {
display: true,
position: 'right',
labels: {
boxWidth: 12
}
}
};
const chartData =
[{
label: 'SomeLabel',
data: this.props.chartData.values,
yAxisId: 'yAxisA',
type: 'doughnut',
backgroundColor: ['#a3e1d4', '#dedede', '#9CC3DA', '#0475ad', '#f8ac59', '#ED5565', '#23c6c8', '#c2c2c2', '#1c84c6'],
}];
const title = (<h5>{this.props.title}</h5>);
const doughnutData = {
labels: this.props.chartData.labels,
datasets: chartData
};
const clonedDoughnutData = Object.assign({}, doughnutData);
const chart = (
<CustomDoughnut
data={clonedDoughnutData}
options={chartOptions}
height={150}
/>
);
const noData = (<NoData isDataVolume={false}/>);
const waveLoader = (<WaveLoader loading={this.props.loading}/>);
return (
<div>
<Tile
loading={this.props.overlayLoading}
title={title}
content={this.props.loading ? waveLoader : this.props.chartData.values.length > 0 ? chart : noData}
dynamicElementsService={this.props.dynamicElementsService}
parentView={this.props.parentView}
element={this.props.element}
status={this.props.status}
label={this.props.title}
/>
</div>
);
}
EDIT 1:
All calculations I make in other component, then I'm dispatching them to store, and then I'm getting them from store in parent component and I'm sending values as a props to component with the chart rendering.
This is how I'm handling proper values to labels:
const SomethingValues = [];
this.somethingLabels.forEach(element => {
if (analytics.chartData.Something.Map.get(element)) {
somethingValues.push(analytics.chartData.Something.Map.get(element));
} else {
somethingValues.push(undefined);
}
}
);
I have a parent component in React called "App" that renders a "Calories" child component with a HighCharts implementation.
What I expect is according to the React lifecycle, parent renders child component and then will call componentDidMount(). I then use a fetch to get data async and once done it setState's the parent with a user object. Then it would re-render the child component with user={this.state.user} and it will be available in the child component. But when i log this.props in the child's componentWillReceiveProps the user object doesn't exist. So this line in child component logs "undefined":
componentWillReceiveProps: function(){
const series = this.props.series;
console.log("component Will Receive Props")
console.log(this.props);
}
Here is my full code:
const App = React.createClass({
//parent component to render all elements and hold state
getInitialState(){
return{
user: {},
series: [{
name: 'Jane',
data: [1, 0, 4]
}, {
name: 'John',
data: [5, 7, 3]
}]
};
},
componentDidMount: function(){
const fb_id = location.pathname.replace("/users/","");
fetch("https://someurl.com/usersdata/" + fb_id)
.then(rsp => rsp.json())
.then(json => {
if(json.error && json.error.message){
throw new Error(json.error.message);
}
this.setState({user:json}, ()=>{
console.log("state updated");
console.log(this.state);
});
});
},
render: function(){
return (
<div className="container">
<div clasNames="row">
<div className="col-xs-12">
{/*Send this.state.user data from fetch to child component*/}
<Calories series={this.state.series} user={this.state.user}/>
</div>
</div>
<div className="row">
<div className="col-xs-7">
<div className="bottom-left" id="weight-line-chart">
<Weight/>
</div>
</div>
<div className="col-xs-5">
<div className="bottom-right" id="avg-calories-pie-chart">
<AverageCal/>
</div>
</div>
</div>
</div>
);
}
});
//Calories Line chart
const Calories = React.createClass({
componentDidMount: function(){
const series = this.props.series;
console.log("component Did Mount");
console.log(this.props);
$(function () {
const myChart = Highcharts.chart('calories-line-chart', {
chart: {
type: 'line'
},
title: {
text: 'Your Calories Over Time'
},
xAxis: {
categories: ['Apples', 'Bananas', 'Oranges']
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: series
});
});
},
componentWillReceiveProps: function(){
const series = this.props.series;
console.log("component Will Receive Props")
console.log(this.props);
$(function () {
const myChart = Highcharts.chart('calories-line-chart', {
chart: {
type: 'line'
},
title: {
text: 'Your Calories Over Time'
},
xAxis: {
categories: ['Apples', 'Bananas', 'Oranges']
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: series
});
});
},
render:function(){
return(
<div>
<h3>Calories Intake</h3>
<div className="top" id="calories-line-chart">
</div>
</div>
);
}
});
Anybody can help me what I am doing wrong?
componentWillReceiveProps get called when props values of child (inside parent component) will get updated, you need to receive the new values as a parameter in this lifecycle method, like this:
componentWillReceiveProps: function(newProps){ //here
console.log("component Will Receive Props", newProps); //it will log the new values
...
}
this.props inside componentWillReceiveProps will have the previous values and it will get updated after this lifecycle method. If you do console.log(this.props) inside render, you will see the updated values.
Why we need to receive the new values as parameter?
I think reason is (not sure), this method get called whenever we do setState in parent component, irrespective of whether that is related to child component or not, so we need to put some logic before doing any task in child (new props and old props are same or not), because of that this.props will have the old values inside this method.
Check the DOC for more details on componentWillReceiveProps.