Error while parsing a string that I receive from backend - javascript

I'm currently using ChartJS for displaying a chart and in that, I'm receiving all the data from the backend. The problem is that the options properties like chart header, yaxis ticks, etc aren't being added to the chart.
Here is my Universal Chart component:
class UniversalChart extends Component {
constructor(props) {
super(props);
}
chartRef = React.createRef();
componentDidMount() {
const myChartRef = this.chartRef.current.getContext("2d");
console.log('options Data inside Uni Chart',this.props.options);
new Chart(myChartRef, {
type: this.props.type,
data: { labels: this.props.labels, datasets: this.props.data },
options: this.props.options
})
}
render() {
return <canvas ref={this.chartRef} height={this.props.height} />
}
}
Here is data that I receive from options inside of my Universal Chart component: {"responsive":true,"title":{"display":true,"text":"Sales trend"},"legend":{"position":"bottom"},"scales":{"yAxes":[{"ticks":{"beginAtZero":true,"stepSize":20}}]}}
Here is a screenshot of the console log:
Also, here is the screenshot of the chartOptions data that I receive in the ChartBox component and which I pass it down to Universal chart.
I pass down the data to Universal Chart component from the parent ChartBox component like this:
<UniversalChart
type={props.data.chart_data_config.chartType}
data={props.data.datasets}
labels ={props.data.labels}
options={props.data.chart_data_config.chartOptions}
height={props.data.chart_data_config.height}
/>
I also tried this inside my Universal Chart comp:
options: JSON.parse(this.props.options)
But that's giving me a cross-origin error: Uncaught Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development.
Please let me know the solution to the problem. I want the UniversalChart comp to read the options json that I'm passing to show the chart header and utilize the other properties.

Related

Can we render the extended component and wrap the render?

Actually I wanted to create a custom component for rechart using the component from the rechart library. When I try to render the data i am unable to see the output. Let me show you some example.
import { LineChart as ReLineChart} from 'recharts';
export class MyLine extends ReLine {
static defaultProps = {
...ReLine.defaultProps,
// Customized props
strokeWidth: 2,
dot: false,
};
}
When I use <MyLine /> it is rendering properly and I can see the output in the browser a Line drawn and I can also pass the props required in the jsx. But when I use a render function in the class component the line is not getting rendered. Can anyone provide me a solution to get it rendered
export class MyLine extends ReLine {
static defaultProps = {
...ReLine.defaultProps,
// Customized props
strokeWidth: 2,
dot: false,
};
render(){
return <div>{}</div>
}
Provide me a solution.

Reload chart on api call

I'm trying to reload the data on a bar chart from chart.js, but im not able to.
This is the chart:
<script>
import { Bar } from 'vue-chartjs'
export default {
extends: Bar,
props: ["chartdata"],
data: () => ({
options: {
responsive: true,
maintainAspectRatio: false
}
}),
computed: {
chartData: function() {
return this.data;
}
},
watch: {
data: function() {
this._chart.destroy();
this.renderChart(this.data, this.options);
}
},
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
</script>
This is how I implement it:
<chart
:chartdata="chartdata"
:options="options"/>
After getting the data from the api and form the chartdata I try to trigger the watch by updating the container data that I'm sending like this:
const cd = {
labels: labels,
datasets: [{
label: '# of Votes',
data: data
}]}
this.chartdata = cd
}
But It's not working and I don't know why.
Neither familiar with the library or vue.js in general, but the documentation says the following about updating the chart...
Chart.js does not provide a live update if you change the datasets.
However, vue-chartjs provides two mixins to achieve this.
reactiveProp reactiveData Both mixins do actually achieve the same.
Most of the time you will use reactiveProp. It extends the logic of
your chart component and automatically creates a prop named chartData
and adds a vue watch on this prop. On data change, it will either call
update() if only the data inside the datasets has changed or
renderChart() if new datasets were added.
You're not using the mentioned props in the documentation. You can read more it on the official documentation
If you are using vue-chartjs, the library has its own way to handle reactive data in charts:
// ChartBar.js
import { Bar, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Bar,
mixins: [reactiveProp],
props: ['options'], // passed from the parent
mounted () {
// this.chartData is created in the mixin (pass it as any prop with :chart-data="data").
this.renderChart(this.chartData, this.options)
}
}
Now use the component
<chart
:chart-data="chartdata"
:options="options"
/>
You can read more about it here: https://vue-chartjs.org/guide/#updating-charts,
there are some caveats

How do I return a JSON array in React from a local file and have it map through all of my items?

Notes: using React for this.
Basically, I'm just trying to make a list of anchor elements from a list of links I have stored locally in a json file. I can confirm that the file is successfully seeing the "endpoints" data through console logs. However, the page just renders a white page and it doesn't look like the state is getting set correctly with the imported array.
So, this is what my file looks like right now (Any help would be greatly appreciated!):
import React from 'react';
import endpoints from './endpoints.json';
class Link extends React.Component{
constructor(props){
super(props);
this.state = {
error: null,
isLoaded: false,
myData: []
};
}
componentDidMount() {
let myData = endpoints.map((data, key) => {
console.log(endpoints);
console.log(endpoints[0].key);
return(
<a className="aLink" href={endpoints.link} key={endpoints.key} >{endpoints.name}</a>
)
})
this.setState({myData: myData});
console.log(this.state.myData);
}
render() {
const { error, isLoaded } = this.state;
if (error) {
return <div className="errorM">Error: {error.message}</div>;
} else {
return(
<div>
{this.state.myData}
</div>
)
}
}
}
export default Link;
You seem to be trying to render from the initial response (endpoints) rather than the map value (data). Change
href={endpoints.link} key={endpoints.key} >{endpoints.name}
to
href={data.link} key={data.key} >{data.name}
Well, this was one of those classic, ask a question and then immediately figure out the answer. Basically, where I'm mapping each item, I set an argument called "data". Instead of calling "endpoints.xxx" it should be "data.xxx" for everything. Then, everything renders fine. :)

Why won't my child component render props?

I have set up a React Frontend with a Node backend for an app I am trying to make. I have successfully created a server which is hosting my data, which I can then access and receive into my React Frontend. I am able to console.log the data I want and successfully saved it to the state (I think?). My issue is that I can't seem to actually pass the information contained in State into the child component.
Units.js
import UnitsCard from "./InfoCardUnits";
import React, { Component } from "react";
const axios = require("axios");
class Units extends Component {
constructor(props) {
super(props);
this.state = {
units: []
};
}
fetchData() {
axios
.get("http://localhost:3001/allData/units")
.then(response => {
// handle success
// console.log("Success");
this.setState({ units: response.data });
})
.catch(error => {
// handle error
console.error(error);
});
}
componentDidMount() {
this.fetchData();
}
render() {
// this console.log will show the data I want to send as props into my child component.
console.log(this.state.units[0]);
return <UnitsCard props={this.state.units[0]} />;
}
}
export default Units;
InfoUnitCard.js
import "../index.css";
function UnitsCard(props) {
// this console.log will show the "props" information that I want to use in my unit card. But the information itself won't actually show in the browser.
console.log(props);
return (
<div className="card">
<h2>{props.name}</h2>
<h2>{props.category}</h2>
<h2>{props.inf_melee}</h2>
</div>
);
}
export default UnitsCard;
When I console.log the state in either of the components it successfully shows the information I am trying to send. But I can't actually get that information to render. Any help or insights would be much appreciated.
EDIT: This has been resolved, thanks very much to everyone who chipped in an answer.
Avoid passing props in via the props keyword. Instead, consider making the following changes to your code:
render() {
// Get unit or empty object (makes code more readable in next step)
const unit = this.state.units[0] || {};
// Pass each piece of unit data in as a separate prop
return <UnitsCard
name={unit.name}
category={unit.category}
inf_melee={unit.inf_melee} />;
}
Alternatively, you could use the "spread" syntax available with ES6 to make this a little more concise:
render() {
// Get unit or empty object (makes code more readable in next step)
const unit = this.state.units[0] || {};
// Use spread operator to simplify passing of props to UnitsCard
return <UnitsCard {...unit} />;
}
Every thing you pass in the child component will be available in props object in the child component. In your case you are passing a 'props' to props object. This should be available as this.props.props.keyname. try changing your child component as follow.
function UnitsCard(props) {
// this console.log will show the "props" information that I want to use in my unit card. But the information itself won't actually show in the browser.
console.log(props);
return (
<div className="card">
<h2>{props.props.name}</h2>
<h2>{props.props.category}</h2>
<h2>{props.props.inf_melee}</h2>
</div>
);
}
You named your props props, so you can access to it with below code:
console.log(props.props);
you can pass like with a different name:
<UnitsCard child={this.state.units[0]} />
Then access to props with props.child, so your code will change to:
<h2>{props.child.name}</h2>

Can AnyChart the HTML version be used with React?

I would like to use AnyChart library with my current React, Redux stack. Is there a way to wrap AnyCharts in something like FauxDom. Would be nice if you can provide me with a sample code snippet or direction to a library that does that.
As for the client side React rendering, it is surely possible to use AnyChart wrapped in a React component.
You could write a wrapping AnyChart component accepting the data array and title as props in this way (example of a pie chart wrapper):
import React, { Component } from 'react';
class AnyChart extends Component {
constructor(props) {
super(props);
}
// Important, otherwise the re-render
// will destroy your chart
shouldComponentUpdate() {
return false;
}
componentDidMount() {
// Get data from the props
let data = this.props.data;
let title = this.props.title;
// Let's draw the chart
anychart.onDocumentReady(function() {
let chart = anychart.pie(data);
chart.container('chart');
chart.title(title);
chart.draw();
});
}
render() {
return (
<div id="chart" style={{height: '400px'}}/>
);
}
}
export default AnyChart;
You can then use this component from another react component.
For example, from a functional component:
import React from 'react';
import AnyChart from './AnyChart';
const AnyChartTest = (props) => {
const data = [
['React', 5200],
['ES6', 2820],
['Redux', 2650],
['Redux Ducks', 670]
];
return (
<div>
<h1>AnyChart Test</h1>
<AnyChart data={data} title="Technology Adoption" />
</div>
);
};
export default AnyChartTest;
This works well if you don't need to have the chart dynamically updated with new data from the props. If that is the case you should add a ComponentWillReceiveProps handler in the AnyChart wrapper component, where you should pass new data from the props to the chart and force a redraw.
Stephen Grider made a very good video on third party components integration:
https://www.youtube.com/watch?v=GWVjMHDKSfU
I hope I helped you, at least for client-side rendering.
Matteo Frana

Categories

Resources