Related
I am using React with hooks to pass filtered values to a chart.
The problem is that i was no able to pass the "filterData" values to the chart:
const filterData = data.datasets[0].data.filter(value => value > Number(filterdatanumber))
Any suggestion on how can i solve this?
I have tried different solutions existing in these videos https://www.youtube.com/watch?v=cz2rG-OVXXU, or create a new variable, among others, however nothing worked.
The complete code:
import React, { useState } from 'react';
import { Bar } from 'react-chartjs-2';
export default function VerticalBar() {
const [firstNumber, setFirstNumber] = useState("");
const textChangeHandler = (i) => {
setFirstNumber(i.target.value);
console.log("target.value", i.target.value);
filterChart(Number(i.target.value));
};
const data = {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [{
label: 'Weekly Sales',
data: [18, 12, 6, 9, 11, 3, 9],
backgroundColor: [
'rgba(255, 26, 104, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(0, 0, 0, 0.2)'
],
borderColor: [
'rgba(255, 26, 104, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
'rgba(0, 0, 0, 1)'
],
borderWidth: 1
}]
};
const filterChart = (filterdatanumber = Number.MIN_SAFE_INTEGER) => {
const filterData = data.datasets[0].data.filter(value => value > Number(filterdatanumber))
// const filterData = data.datasets[0].data.filter(value => value > 9)
const filterLabels = [];
const filterColors = [];
let i = 0;
for (i; i < filterData.length; i++) {
const result = data.datasets[0].data.indexOf(filterData[i]);
const labelsResult = data.labels[result];
const colorssResult = data.datasets[0].backgroundColor[result];
filterLabels.push(labelsResult );
filterColors.push(colorssResult);
}
console.log("filterData", filterData)
console.log("filterLabels", filterLabels)
console.log("filterColors",filterColors)
data.datasets[0].data = filterData;
data.labels = filterLabels;
data.datasets[0].backgroundColor = filterColors;
}
filterChart();
return (
<div >
<Bar data={data} />
<input value={firstNumber} type="number" name="firstNumber" onChange={textChangeHandler} />
</div>
)
}
your code has many problems regarding how you handle state date inside the component.
If data is constant then you can move it outside the component.
The function filterData can be replaced with a state holding the filtered data and a useEffect that will be triggered when another filterdatanumber state changes.
Here is an example code with these changes.
import React, { useState, useEffect } from "react";
import { Bar } from "react-chartjs-2";
const data = {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
datasets: [
{
label: "Weekly Sales",
data: [18, 12, 6, 9, 11, 3, 9],
backgroundColor: [
"rgba(255, 26, 104, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)",
"rgba(0, 0, 0, 0.2)",
],
borderColor: [
"rgba(255, 26, 104, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)",
"rgba(0, 0, 0, 1)",
],
borderWidth: 1,
},
],
};
export default function VerticalBar() {
const [firstNumber, setFirstNumber] = useState("");
const [filterdatanumber, setFilterdatanumber] = useState(
Number.MIN_SAFE_INTEGER
);
const [filteredData, setFilteredData] = useState(data);
const textChangeHandler = (i) => {
setFirstNumber(i.target.value);
console.log("target.value", i.target.value);
filterChart(Number(i.target.value));
};
useEffect(() => {
const newData = { ...data };
const filteredData = [];
const filterLabels = [];
const filterColors = [];
for (let i = 0; i < newData.datasets[0].data.length; i++) {
const value = newData.datasets[0].data[i]
if (value > Number(filterdatanumber)) {
const labelsResult = newData.labels[i];
const colorssResult = newData.datasets[0].backgroundColor[i];
filterLabels.push(labelsResult);
filterColors.push(colorssResult);
filteredData.push(value)
}
}
console.log("filteredData", filteredData);
console.log("filterLabels", filterLabels);
console.log("filterColors", filterColors);
newData.datasets[0].data = filteredData;
newData.labels = filterLabels;
newData.datasets[0].backgroundColor = filterColors;
setFilteredData(newData);
}, [filterdatanumber]);
return (
<div>
<Bar data={filteredData} />
<input
value={firstNumber}
type="number"
name="firstNumber"
onChange={textChangeHandler}
/>
</div>
);
}
Please remember that this code is just an example, maybe it will need some edits in order to match your needs.
Here is my final solution fully working and with a refactored 3rd approach. The values are matching the keys consistently when filtered and displayed correctly in the chart.
import React, { useState, useEffect, useCallback, useMemo } from "react";
import { Bar } from "react-chartjs-2";
export default function VerticalBar() {
const [data, setData] = useState ([
{val: 18, label: "Mon"},
{val: 1, label: "Tue"},
{val: 5, label: "Wed"},
{val: 8, label: "Thu"},
{val: 19, label: "Fri"},
{val: 5, label: "Sat"},
{val: 7, label: "Sun"}
])
const chartConfig = useMemo(() => {
return {
labels: data.map(el => el.label),
datasets: [
{
label: "Weekly Sales",
data: data.map(el => el.val),
backgroundColor: [
"rgba(255, 26, 104, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)",
"rgba(0, 0, 0, 0.2)",
],
borderColor: [
"rgba(255, 26, 104, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)",
"rgba(0, 0, 0, 1)",
],
borderWidth: 1,
},
],
};
}, [data])
const textChangeHandler = useCallback(
(event) => {
setData(prevData => {
return prevData.filter((el) => parseInt(event.target.value, 10) < el.val)
})
}, [setData]);
return (
<div>
<Bar data={chartConfig} />
<input
type="number"
name="firstNumber"
onChange={textChangeHandler}
/>
</div>
);
}
I am using React-Chartjs-2 on a project and am getting stuck on updating the filter of my chart. I am following along with the following demo, but this doesn't just the react one, but the vanilla version.https://www.youtube.com/watch?v=Gc5JF2TUG7o&t=679s # 16:32 is the update function to update the filtered dates on the chart. I am able to get the index of the date array, but my chart doesn't update. How am I able to access and update the labels and datasets value within the Line component?
import React from 'react';
import {Line} from 'react-chartjs-2'
function BarChart() {
const dates = ['2021-08-25', '2021-08-26','2021-08-27','2021-08-28', '2021-08-29', '2021-08-30','2021-08-31' ];
const datapoints =[1,2,4,9,12,15,16]
function filterData() {
const dates2 = [...dates];
console.log(dates2);
const startdate = document.getElementById('startdate');
const enddate = document.getElementById('enddate');
//get the index number in the array
const indexstartdate = dates2.indexOf(startdate.value);
const indexenddate = dates2.indexOf(enddate.value);
console.log(indexstartdate);
console.log(indexenddate);
//slice the array
const filterDate = dates2.slice(indexstartdate, indexenddate + 1);
//replace label in the chart
//HELP HERE!!!
}
return (
<div>
<div>
<Line id='myChart'
data={{
labels:dates,
datasets: [
{
label: 'Sales',
data:datapoints,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1,
},
],
}}
height={400}
width={400}
options={{maintainAspectRatio:false,
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
}
}
]
},
}}
/>
</div>
<input type='date' onChange={filterData} id='startdate' />
<input type='date' onChange={filterData} id='enddate' />
</div>
)
}
export default BarChart
You need to use the React state so your component will rerender. Here is my solution, I hope it helps.
import React, { useRef, useState } from "react";
import { Line } from "react-chartjs-2";
function BarChart() {
const initialDates = [
"2021-08-25",
"2021-08-26",
"2021-08-27",
"2021-08-28",
"2021-08-29",
"2021-08-30",
"2021-08-31",
];
const initialDataPoints = [1, 2, 4, 9, 12, 15, 16];
const [dates, setDates] = useState(initialDates);
const [dataPoints, setDataPoints] = useState(initialDataPoints);
console.log(dates, dataPoints);
const inputRef1 = useRef();
const inputRef2 = useRef();
function filterData() {
const dates2 = [...dates];
const dataPoints2 = [...dataPoints];
//slice the array
let value1 = inputRef1.current.value;
let value2 = inputRef2.current.value;
const indexstartdate = dates2.indexOf(value1);
const indexenddate = dates2.indexOf(value2);
console.log(indexstartdate);
console.log(indexenddate);
//slice the array
const filterDate = dates2.slice(indexstartdate, indexenddate + 1);
const filterDataPoints = dataPoints2.slice(
indexstartdate,
indexenddate + 1
);
console.log(filterDate, filterDataPoints);
//replace label in the chart
//HELP HERE!!!
setDates(filterDate);
setDataPoints(filterDataPoints);
console.log(dates, dataPoints);
}
return (
<div>
<div>
<Line
id="myChart"
data={{
labels: dates,
datasets: [
{
label: "Sales",
data: dataPoints,
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)",
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)",
],
borderWidth: 1,
},
],
}}
height={400}
width={400}
options={{
maintainAspectRatio: false,
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
}}
/>
</div>
<input type="date" ref={inputRef1} />
<input type="date" ref={inputRef2} />
<button onClick={filterData}>Filter</button>
</div>
);
}
export default BarChart;
I'm new to react and also just found react-chartjs-2 graphing npm package. So I implemented this to my react project. Now I need to change the grid lines and axis colours to white. So I tried this line of two code also in two times.But it didn't work.
defaults.global.defaultColor='rgba(255,255,255,1)'
defaults.global.defaultColor='rgba(255,255,255,1)'
How can I do that?
Thanks in advance.
You can change the axis grid color using gridLines option. Find more styling options here.
import React from "react";
import "./style.css";
import { Bar } from "react-chartjs-2";
const data = {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "# of Votes",
data: [12, 19, 13, 15, 12, 13],
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)"
],
borderWidth: 1
}
]
};
const options = {
scales: {
yAxes: [
{
gridLines: {
color: "red"
}
}
],
xAxes: [
{
gridLines: {
color: "blue"
}
}
]
}
};
export default function App() {
return (
<div>
<Bar data={data} options={options} />
</div>
);
}
I have created this code example. I am using a React functional component, but for some reason the chart won't render. I think it is because React Hooks does not play nice with conditionals, but I don't understand why.
https://codesandbox.io/s/sparkling-darkness-e7bdj
Why doesn't the chart render?
I am using hooks because I don't want to use a class. It seems like this should work and I am getting no errors.
How can I get it to work?
I found a way to fix it.
Normally, the Chart constructor call goes in componentDidMount. The Hook equivalent is useEffect.
Working code is as follows:
import React, { useRef, useEffect } from "react";
import ReactDOM from "react-dom";
import Chart from "chart.js";
import "./styles.css";
function App() {
const chartRef = useRef(null);
useEffect(() => {
if (chartRef.current) {
const myChart = new Chart(chartRef.current, {
type: "bar",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "# of Votes",
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)"
],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
});
}
});
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<canvas ref={chartRef} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I'm trying to implement a Line chart in my react app. I found this when searching for charts.
https://github.com/reactjs/react-chartjs
I have used this piece of code but it isn't clear how to use chartData and chartOptions
var LineChart = require("react-chartjs").Line;
var MyComponent = React.createClass({
render: function() {
return <LineChart data={chartData} options={chartOptions} width="600" height="250"/>
}
});
How can i declare the chartData and chartOptions inorder to get my Linechart work?
You need to define chartData and chartOptions as objects in your React Component. A sample chartData will look like
For a line Chart
var chartOptions: {
// Boolean - If we should show the scale at all
showScale: true,
// Boolean - Whether to show a dot for each point
pointDot: true,
showLines: false,
title: {
display: true,
text: 'Chart.js Bar Chart'
},
legend: {
display: true,
labels: {
boxWidth: 50,
fontSize: 10,
fontColor: '#bbb',
padding: 5,
}
}
var chartData = {
labels: [['Sunday', 'Monday'], ['Sunday', 'Tuesday']],
datasets: [
{
color: "#4D5360",
highlight: "#616774",
borderColor: "rgba(179,181,198,1)",
pointBackgroundColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(179,181,198,1)",
label: 'Current lag',
fill: false,
lineTension: 0.1,
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
scaleOverride: true, scaleStartValue: 0, scaleStepWidth: 1, scaleSteps: 30,
data: [[5, 8], [3, 11]]
}
]
}
For a barChart
var chartData = {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
var chartOptions = {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
See the docs here for more information on the object properties: