I have been import JSON files from my MongoDB server through axios. I am able to fetch the data successfully but showing it on chart is not possible. I ahve seen other answers and it seems easy to store each key column in a seperate variable and then loading to labels and data objects, but this more optimized and Chartjs also allows us this approach as listed in its documentation but I might be going wrong somewhere. In need for help as I need to implement it for my project
import React, { useState } from 'react';
import axios from 'axios';
import { useEffect } from 'react';
import {Bar, Line} from 'react-chartjs-2';
const URL = process.env.REACT_APP_SERVER_URL || 'http://localhost:5000/';
function ChartRoughPage(props) {
const [historicalData,setHistoricalData] = useState([]);
useEffect(()=>{
axios.get(URL+'stock/BLUEDART')
.then((response)=>{
if(response.status===200){
console.log(response.data)
setHistoricalData(response.data)
}
else{
console.log("ERROR: "+response.status+" , "+response.statusText)
}
})
.catch((err) => console.log.err);
},[]);
return (
<div>
<Line
data={{
datasets:[{
label:'Everyday Chart',
data : historicalData,
parsing:{
xAxisKey:'DATE',
yAxisKey:'CLOSE'
}
}]
}}
/>
</div>
);
}
export default ChartRoughPage;
Output : It just shows a chart with no data
For better understanding here is the link to the documentation:
https://www.chartjs.org/docs/latest/general/data-structures.html
Also I have tried following things on my code:
Tried writing it to options
...
<Line
data={{
datasets:[{
data : historicalData
}]
}}
options={{
parsing:{
xAxisKey:'Date',
yAxisKey:'Close'
}
}}
/>
...
Providing a static data like:
historicalData = [{Date : '22-02-2000',Close: 56},{Date : '22-03-2000',Close: 656},{Date : '23-05-2000',Close: 6}]
also the documents that I send as JSON from MongoDB is like this is(all the values are accessible by their keys):
{"_id":{"$oid":"some-object-id"},"Date":"2019-01-03","Symbol":"20MICRONS","Series":"EQ","Prev Close":{"$numberDouble":"44.05"},"Open":{"$numberDouble":"44.05"},"High":{"$numberDouble":"44.1"},"Low":{"$numberDouble":"43.1"},"Last":{"$numberDouble":"43.4"},"Close":{"$numberDouble":"43.45"},"VWAP":{"$numberDouble":"43.48"},"Volume":{"$numberInt":"15741"},"Turnover":{"$numberDouble":"68447485000.0"},"Trades":{"$numberDouble":"368.0"},"Deliverable Volume":{"$numberInt":"9487"},"%Deliverble":{"$numberDouble":"0.6027"}}
Will be grateful for your help!
It seems the issue is in the type of the x-axis, cause if you provide
datasets: [{
data: [{Date : '11',Close: 56},{Date : '22',Close: 656},{Date : '23',Close: 6}],
showLine: true,
fill: false,
borderWidth: 1,
parsing: {
xAxisKey: 'Date',
yAxisKey: 'Close'
},
backgroundColor: 'rgba(255, 99, 132, 1)'
}]
it draws just fine
So you should better find how to show time on the x-axis
I know I am late, but I have to answer this)
Related
First, I would like to emphasize that I am a completely new to Vue (and webdev in general).
I have to make a UI where I have to show some data that I fetch from an API. But I have some issues with chart.js: I can't update my chart when prop change.
Currently, I have the following setup:
Card.vue:
<script>
import DoughnutChart from './DoughnutChart.js'
export default {
name: 'Card',
components: {
DoughnutChart
},
props: ['scheda'],
created() {
console.log(this.scheda)
}
}
</script>
<template>
<DoughnutChart type="abcd" :chartData="this.scheda"/>
</template>
DoughnutChart.js:
import { defineComponent, h } from 'vue'
import { Doughnut } from 'vue-chartjs'
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
ArcElement,
CategoryScale
} from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale)
export default defineComponent({
name: 'DoughnutChart',
components: {
Doughnut
},
props: ['type', 'chartData'],
setup(props) {
const chartData = {
labels: ['A', 'B'],
datasets: [
{
backgroundColor: ["#ff3333", "#131b2e"],
cutout: "75%",
borderWidth: 0,
data: [props.chartData.value, (100 - props.chartData.value)]
}
]
}
const chartOptions = {
plugins: {
legend: {
display: false
}
},
responsive: true,
maintainAspectRatio: false
}
return () =>
h(Doughnut, {
chartData,
chartOptions
})
}
})
this.scheda is a reactive value and when it changes the chart should update accordingly.
I have read the documentation, but I simply can't wrap my head around it.
I have also tried searching on the internet, but all examples reference the older version of the chart library.
Can someone help me with this issue? Thanks!
If you want to create a chart js and integrate with view, you can create your canvas on js outside of vue js flow, and then get the element reference inside vue and then integrate it, the big problem rendering components inside vue is that you need update your charts, it may cause unexpected behavior on canvas. Because tools like Vue are designed to refresh the html and canvas always are a single html tag with a lot of interactivity in js(not much html).
Vue-chart
You can install
vue-chart.js
It supports data updates and also you can access to the chart ref.
Updating charts: https://vue-chartjs.org/guide/#updating-charts
Acesing to ref: https://vue-chartjs.org/guide/#access-to-chart-instance
I am attempting to create charts with chart.js. I have followed the example code on the chart.js website and have been able to get the example code to work. I have tried amending the code to process the data for the chart externally from the javascript file creating the chart, then providing the data through the chart parameters. Doing this, I get the following console error:
I have the following data in my data.js file:
export const UserData = [
{
id: 1,
year: 2018,
users: 2000,
},
{
id: 2,
year: 2019,
users: 2500,
},
{
id: 3,
year: 2020,
users: 3000,
}
]
I have the following code in my App.js file:
import React from "react";
import { UserData } from './Components/data';
import { Graph } from "./Components/graph";
const data = {
labels: UserData.map((data) => data.year),
datasets: [{
label: 'Revenue',
data: UserData.map((data) => data.users),
backgroundColor: ['#CCD4BF'],
borderColor: [],
borderWidth: 1
}]
};
function App() {
return <Graph graphData={data}/>
}
I have the following code in my graph.js file:
import React from 'react';
import { Bar } from 'react-chartjs-2';
import {Chart as ChartJS,} from 'chart.js/auto'
export function Graph(graphData) {
return <Bar data={graphData}/>
}
Is there anything that I am missing in my code to resolve the "reading map" and "ForwardRef" errors?
I had the same issue, to solve this read about migration to react-chartjs-2#4 here, that helped for me, I used the tree-shakable approach:
import { Chart } from 'react-chartjs-2';
import { Chart as ChartJS, LineController, LineElement, PointElement, LinearScale, Title } from 'chart.js';
ChartJS.register(LineController, LineElement, PointElement, LinearScale, Title);
<Chart type='line' data={chartData} />
I recently started working with chart.js with react wrapper for a project. And when I was building this one chart which has a width of 20000px the bars stopped appearing on the screen after the 16390px length.
My chart was scrollable and I had a large dataset due to which the canvas have huge lengths. So I was confused if there is some length limit chart.js can draw its canvas upto.
Here is my code to replicate the issue with attached screenshots.
import React, { Component, createRef } from 'react'
import ChartJsComponent from "react-chartjs-2";
class ScrollableChartJsPlugin extends Component {
chartRef = createRef()
render(){ //this will simply return the chart
return <ChartJsComponent
ref={this.chartRef}
{...this.props}
/>
}
}
export default ScrollableChartJsPlugin;
import React, { Component } from 'react'
import ScrollableChart from "../../components/ScrollableChartJSPlugin";
class Observe extends Component {
getRandomLabel = () => {
let data = [];
for(let i = 0; i<1000; i++){
data.push(`Label ${i}`)
}
return data;
}
render(){
var data = {
labels: this.getRandomLabel(),
datasets: [
{
backgroundColor: 'rgba(237, 77, 77,1)',
borderColor: 'rgba(237, 77, 77,1)',
borderWidth: 1,
hoverBackgroundColor: 'rgba(237, 77, 77,0.8)',
hoverBorderColor: 'rgba(237, 77, 77,1)',
data: this.getRandomLabel().map(el => 1000) //i am taking same value for all the bars as it'll be easier to catch when bars disappears
}
]
};
var width = this.getRandomLabel().length * 50; //this will give each bar around 50px width and total width of the chart will go around 50000px
return <div style={{width: width}}>
<ScrollableChart
type={"bar"}
height={220}
width={width}
data={data}
getElementAtEvent={this.handleChartClick}
options={
{
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display:false
}
}],
yAxes: [{
gridLines: {
display:false
}
}]
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
/>
</div>
}
}
export default Observe;
screenshot produced by the result of the above code.
So, In case there is a max width limit in chart.js for drawable canvas, Can I get it work with any workaround or any fix that is applicable for this.
Thanks
Posting for anyone who will be struggling with similar issue in the future.
After a lot of research for last two days. I found out the problem was basically with the browser.
Actually there is a limit a browser can draw a canvas upto after that limit no draw command works and the chart is not drawn any further.
checkout below thread for details.
Maximum size of a <canvas> element
That was the details of the problem. And for solution, in our case we were fetching the data from an api and then was showing in the chart, so we restricted the the max data we can hold and started deleting elements previously loaded as more data is loaded.
And that worked for us.
You can also check out this thread on github regarding this issue.
https://github.com/chartjs/Chart.js/issues/6068
I am able to create QR Code with single value by using react-native-qrcode-svg package. But not able to add multiple values like name,email, etc.
I have tried these :
Packages:
npm install react-native-svg --save
react-native link react-native-svg
npm install react-native-qrcode-svg --save
Code for generating QR Code using single value.
import * as React from 'react';
import QRCode from 'react-native-qrcode-svg';
export default class App extends React.Component {
render() {
return (
<QRCode
value="Here I want to add name, email,etc"
/>
);
};
}
I want to generate something like this
You can use rn-qr-generator module to create QRCode Image with a given string.
To generate a QRCode image with an object just do something like this
import RNQRGenerator from 'rn-qr-generator';
RNQRGenerator.generate({
value: JSON.stringify({ email: 'some.email.com', name: 'Name' })
height: 100,
width: 100,
base64: false, // default 'false'
backgroundColor: 'black', // default 'white'
color: 'white', // default 'black'
})
.then(response => {
const { uri, width, height, base64 } = response;
this.setState({ imageUri: uri });
})
.catch(error => console.log('Cannot create QR code', error));
According to the documentation here, https://www.npmjs.com/package/react-native-qrcode-svg, the value can be an array:
String Value of the QR code. Can also accept an array of segments as defined in Manual mode. Ex. [{ data: 'ABCDEFG', mode: 'alphanumeric' }, { data: '0123456', mode: 'numeric' }, { data: [253,254,255], mode: 'byte' }]
Hence the code should be
import * as React from 'react';
import QRCode from 'react-native-qrcode-svg';
export default class App extends React.Component {
render() {
return (
<QRCode
value="[{ name: 'my name'},{ email: 'email#email.com' }]"
/>
);
};
}
I never used react, but shouldn't be something like
value={`"name={name},email={email},phone={phone}"`}
enough to compute the value?
<QRCode
value={`${email},${mdp}`}
/>
if you want to read the data:
data=result.split(",")
I am trying to render a Line chart using react-chartjs-2. Right now it works fine when I pass in static props to the Line Component. But, when I fetch data from an API, set it to a variable, then pass that variable as the prop. My Line Component is not re-rendering with the new data.
I am logging the props being passed into the Line Component and I can see it first arrives as null and then I receive the good data from the API. So it looks like the Line Component is not re-rendering after receiving the props? I am probably doing this wrong. Please help.
import React from "react";
import { Line } from "react-chartjs-2";
export default class ExpenseChart extends React.Component {
constructor(props) {
super(props);
this.state = {
marketData: [100, 200, 300],
chartData: {
labels: this.props.monthNames,
datasets: [
{
backgroundColor: "rgba(142, 243, 197, 0.5)",
pointBackgroundColor: "#fff",
pointHoverBackgroundColor: '#fff',
pointStyle: "circle",
label: "Monthly Expenses",
borderColor: "#2be1d8",
borderWidth: 3,
borderJoinStyle: "round",
lineTension: 0.3,
fontColor: "#fff",
hitRadius: 5,
hoverRadius: 8,
radius: 4,
data: this.props.monthExpenses
},
],
},
};
}
render() {
console.log("why no names", this.props.monthNames)
return (
<div className="expenseChart">
<h2 className="expenseChart__name">{this.props.graphname}</h2>
<Line
data={this.state.chartData}
options={{
maintainAspectRatio: false,
responsive: true,
aspectRatio: 3,
scales: {
yAxes: [
{
ticks: {
display: false,
},
},
],
},
layout: {
padding: {
right: 10,
},
},
}}
/>
</div>
);
}
}
And then the parent component is connected to a redux store and it looks like this:
import React from "react";
import { connect } from 'react-redux';
import ExpenseChart from "../elements/ExpenseChart";
import { fetchExpenses } from '../../actions/index';
class Dashboard extends React.Component {
componentDidMount() {
this.props.dispatch(fetchExpenses());
}
render() {
let labels = this.props.months && this.props.months;
return (
<main className="dashboard">
<ExpenseChart
monthNames={labels}
monthExpenses={["123", "123", "12312", "12341", "231231", "1231", "1231"]}
// I am receiving monthExpenses props into the ExpenseChart component
// but not monthNames
/>
</main>
);
}
}
const mapStateToProps = state => ({
auth: state.app.auth,
months: state.app.months,
});
export default connect(mapStateToProps)(Dashboard);
I've done something similar before, fetching data from an API and passing it as props to the Line Component. But only difference is I am using redux here. And obviously, this time the Line Component is not receiving the good data.
The issue might be on this componentDidMount code.
componentDidMount() {
this.props.dispatch(fetchExpenses());
}
As per docs on dispatch
action (Object†): A plain object describing the change that makes
sense for your application. Actions are the only way to get data into
the store, so any data, whether from the UI events, network callbacks,
or other sources such as WebSockets needs to eventually be dispatched
as actions. Actions must have a type field that indicates the type of
action being performed. Types can be defined as constants and imported
from another module. It's better to use strings for type than Symbols
because strings are serializable. Other than type, the structure of an
action object is really up to you. If you're interested, check out
Flux Standard Action for recommendations on how actions could be
constructed.
Here fetchExpenses might be returning a promise and in that case you might need
fetchExpenses().then(apiRes => dipatch({type: "ACTION_TYPE": payload: apiRes}))
Another approach can be to use redux-thunk
Ok I solved this just by checking if the data I was receiving was not null before passing it as props. Which is what I thought this line would do let labels = this.props.months && this.props.months;
<main className="dashboard">
{ this.props.months != null ? <ExpenseChart monthNames={labels}/> : ''; }
</main>