referenceError: Can't find variable in react-native with fetch - react-native

hey im trying to make a chart using victory from the data online json data in react native. the code for the component is like below
export default class Dashboard extends Component {
static navigationOption = {
title: 'DashboardScreen'
}
state = {
getValue: '',
dataSource:[],
isLoading: true
}
componentDidMount() {
const url = 'myurl';
fetch(url, {
method: 'GET',
headers: new Headers({
'Content-Type' : 'application/json',
})
})
.then((response)=> response.json() )
.then((responseJson) => {
console.log(responseJson.Views)
this.setState({
dataSource: responseJson,
isLoading: false
})
})
.catch((Error) => {
console.log(Error)
})
}
render() {
return(
<View style = {styles.container}>
<VictoryChart minDomain={{ y: 0, x:0 }} width={350} theme={VictoryTheme.material}>
<VictoryBar
style={{
data: { stroke: "#c43a31" },
parent: { border: "1px solid #ccc"}
}}
data={[
{ x: 1, y: 1 },
{ x: 2, y: dataSource[0].views},
{ x: 3, y: dataSource[1].views},
{ x: 4, y: dataSource[2].views},
{ x: 5, y: dataSource[3].views}
]}>
</VictoryBar>
</VictoryChart>
</View>
)
}
}
i thought the fetch already make the json information an array in dataSource Variable and can be used as a data in victory but i always got error like referenceError: Can't find variable 'dataSource'
So, it would be very nice if anyone helps me out with this code and suggest how make the json data into chart

change:
data={[
{ x: 1, y: 1 },
{ x: 2, y: dataSource[0].views},
{ x: 3, y: dataSource[1].views},
{ x: 4, y: dataSource[2].views},
{ x: 5, y: dataSource[3].views}
]}>
to
data={[
{ x: 1, y: 1 },
{ x: 2, y: this.state.dataSource[0].views},
{ x: 3, y: this.state.dataSource[1].views},
{ x: 4, y: this.state.dataSource[2].views},
{ x: 5, y: this.state.dataSource[3].views}
]}>
Hope this helps!

Related

Get current state of graph after elements are added dynamically

I am using Cytoscape.js and the context menus extension within a React app through react-cytoscape.js. Right now, I can dynamically add nodes through an onClickFunction as a menu item. I would like to get the current state of the graph - that is, all the nodes that have been added as well as the ones it started with.
How can I do this? So far, I've tried cy.json(), but that only returns the initial state of the graph.
Below is all of my cytoscape code.
class MyApp extends React.Component {
constructor(props){
super(props);
}
render(){
const elements = [ // Nodes and edges to be added initially
{ data: { id: 'one', label: 'Node 1' }, position: { x: 250, y: 250 } },
{ data: { id: 'two', label: 'Node 2' }, position: { x: 300, y: 250 } },
{ data: { source: 'one', target: 'two', label: 'Edge from Node1 to Node2' } }
];
return <CytoscapeComponent
cy = {cy => { // Extensions and their options
cy.contextMenus({
menuItems: [
{ // Adds the ability to add nodes from the right-click menu
id: 'add-node',
content: 'add node',
tooltipText: 'add node',
image: {src: "./node_modules/cytoscape-context-menus/assets/add.svg", width: 12, height: 12, x: 6, y: 4},
coreAsWell: true,
// When we move adding nodes to a sidebar, probably use this as reference
onClickFunction: function (event) {
var data = {
group: 'nodes'
};
var pos = event.position || event.cyPosition;
cy.add({
data: data,
position: {
x: pos.x,
y: pos.y
}
});
}
}
]
})
}}
elements={elements}
style={ { width: '100%', height: '40vmax'} } />;
}
}

How to arrange the x axis lables wihtout overlapping in victory-native stacked bar chart

I have a stacked bar chart, whose x axis labels would be date, the labels are overlapping how do I arrange them in such a way that it does not overlap on the next label of x axis.
I did not get how to arrange them changing the angle of the label, can anyone help me out solving the problem.
current graph image
victory-native
react-native-svg
const myDataset = [
[
{ x: "20/10/2020", y: 18653 },
{ x: "21/10/2020", y: 20000 },
{ x: "23/10/2020", y: 97345 },
{ x: "24/10/2020", y: 25687 },
{ x: "25/10/2020", y: 89761 }
],
[
{ x: "20/10/2020", y: 4566 },
{ x: "21/10/2020", y: 3888 },
{ x: "23/10/2020", y: 4975 },
{ x: "24/10/2020", y: 5965 },
{ x: "25/10/2020", y: 5768 }
],
];
class App extends React.Component {
// This is an example of a function you might use to transform your data to make 100% data
transformData(dataset) {
const totals = dataset[0].map((data, i) => {
return dataset.reduce((memo, curr) => {
return memo + curr[i].y;
}, 0);
});
return dataset.map((data) => {
return data.map((datum, i) => {
return { x: datum.x, y: (datum.y / totals[i]) * 100 };
});
});
}
render() {
const dataset = this.transformData(myDataset);
return (
<div>
<VictoryChart height={400} width={400}
domain={{ x: [0,5], y: [0, 100000] }}
domainPadding={{ x: 30, y: 20 }}
>
<VictoryLegend x={280} y={0}
gutter={50}
style={{title: {fontSize: 20 } }}
data={[
{ name: "Tax", symbol: { fill: "blue" } },
{ name: "Amount", symbol: { fill: "black" } }
]}
/>
<VictoryStack
colorScale={["black", "blue"]}
>
{myDataset.map((data, i) => {
return <VictoryBar barWidth={20}
data={data} key={i} labelComponent={<VictoryLabel y={250} verticalAnchor={"start"}/>}/>;
})}
</VictoryStack>
<VictoryAxis dependentAxis />
<VictoryAxis
padding={{ left: 80, right: 60 }}
axisLabelComponent={<VictoryLabel angle={20}/>}
tickFormat={["20/oct/20","21/oct/20", "23/oct/20","24/oct/20","25/10/20"]}/>
</VictoryChart>
</div>
);
}
}
ReactDOM.render(<App/>, mountNode);
The above code can be copy pasted in below link and can edit
https://formidable.com/open-source/victory/gallery/100-column-chart/
Is there any way that I could arrange them like below.
I've gotten it to work by passing a VictoryLabel with a -45 degree angle to the tickLabelComponent prop on your independent axis:
<VictoryAxis tickLabelComponent={<VictoryLabel angle={-45} y={350} />} />
So instead of passing the VictoryLabel to the axisLabelComponent prop on the VictoryAxis, pass it to the tickLabelComponent prop.
https://formidable.com/open-source/victory/docs/victory-axis#ticklabelcomponent
You might also need to add some padding to your VictoryChart component if the labels are cut off:
padding={{top: 100, bottom: 90, left: 70, right: 80}}
https://formidable.com/open-source/victory/docs/victory-axis#padding
This is the solution i used. I had to display time on the x-axis.
In your case, you can take off the tick formatting from the VictoryAxis and let VictoryChart do the date formatting by adding property scale={{x: 'time'}} to VictoryChart
And then add fixLabelOverlap to VictoryAxis which fixes the overlap issue.

Refreshing Konva shape state in Vue component

After dragging and releasing a shape I want it to snap to a close by position. To test this I create a shape at {x:100, y:100}, then drag it and it does snap to 0,0, but only the first time Im dragging it. Next time it will ignore me setting x,y.
I might be missing something basic here? Maybe I am not mutating store the right way. In the below code you can see three attempts to set x and y in handleDragend.
<template>
<div>
<v-stage
ref="stage"
:config="configKonva"
#dragstart="handleDragstart"
#dragend="handleDragend"
>
<v-layer ref="layer">
<v-regular-polygon
v-for="item in list"
:key="item.id"
:config="{
x: item.x,
y: item.y,
sides: 6,
rotation: item.rotation,
id: item.id,
radius: 50,
outerRadius: 50,
fill: 'green',
draggable: true,
}"
></v-regular-polygon>
</v-layer>
</v-stage>
</div>
</template>
<script>
const width = window.innerWidth;
const height = window.innerHeight;
export default {
data() {
return {
list: [],
dragItemId: null,
configKonva: {
width: width,
height: height,
}
};
},
methods: {
handleDragstart(e) {
//
},
handleDragend(e) {
let item = this.list.find(i => i.id === e.target.id());
let snapTo = { x: 0, y: 0}
// Attempt 1
Vue.set(this.list, 0, {
...item,
x: snapTo.x,
y: snapTo.y,
})
// Attempt 2
this.list = this.list.map(function(shape) {
if(shape.id === item.id) {
return {
...item,
x: snapTo.x,
y: snapTo.y,
}
}
})
},
},
mounted() {
this.list.push({
id: 1,
x: 100,
y: 100,
});
}
};
</script>
vue-konva updates nodes ONLY when you have changes in your template.
On the first snap, the coordinated in the template (and store) are changed from {100, 100} to {0, 0}.
When you drag the node the second time, the store still keeps {0, 0} in memory. So no changes are triggered and the node is not moved back.
There are two ways to solve the issue:
(1) Update Konva node position manually
handleDragend(e) {
let item = this.list.find(i => i.id === e.target.id());
let snapTo = { x: 0, y: 0 };
e.target.position(snapTo);
e.target.getLayer().batchDraw();
Vue.set(this.list, 0, {
...item,
x: snapTo.x,
y: snapTo.y
});
}
(2) Keep the store in sync with node position
You may need to register all position changes into the store:
handleDragMove(e) {
// do this on every "dragmove"
let item = this.list.find(i => i.id === e.target.id());
Vue.set(this.list, 0, {
...item,
x: e.target.x(),
y: e.target.y()
});
}
Demo: https://codesandbox.io/s/nifty-northcutt-v52ue

What config and options do I need for react-native-highcharts to make a highstock OHLC graph?

I've been going through HighStock API to try and find which config and options I need to pass to the ChartView component in react-native-highcharts to draw my graph. I'm having a hard time finding what combination of config and options will get my desired result, things like series, dataGrouping, etc... . My data is a 2 dimensional array with 4 values for OHLC. My desired result is the photo at the top of this stackoverflow.
Here is my code so far.
class OHLC extends React.Component {
static navigationOptions = ({ navigation }) => ({
title: "OHLC",
headerLeft: (
<TouchableOpacity
style={NavStyles.headerButton}
onPress={() => navigation.openDrawer()}>
<Icon name="bars" size={20} />
</TouchableOpacity>
),
})
render() {
var Highcharts='Highcharts';
var conf={
title: {
text: 'Stock Name'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Price'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
// tooltip: {
// formatter: function () {
// return '<b>' + this.series.name + '</b><br/>' +
// Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
// Highcharts.numberFormat(this.y, 2);
// }
// },
legend: {
enabled: false
},
// exporting: {
// enabled: false
// },
series: [{
type: 'ohlc',
name: 'AAPL Stock Price',
data: (function () {
let arrays = aExtractFromJson(data,'data', null,null);
arrays = ohlcExtractor(arrays);
return arrays;
// look at toFixed method for number to limit decimal point
}()),
dataGrouping: {
units: [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]]
}
}]
};
const options = {
global: {
useUTC: false
},
lang: {
decimalPoint: ',',
thousandsSep: '.'
}
};
return (
<View>
<ChartView style={{height:300}} config={conf} options={options} stock={true} ></ChartView>
//To see if anything gets rendered.
<Text>HELLO DAVID!</Text>
</View>
);
}
}
After further research, I was able to find the config and options needed to create an OHLC Graph using the ChartView component in react-native-highcharts. I encountered some issues with rendering a blank screen so I added javaScriptEnabled={true} domStorageEnabled={true} originWhitelist={['']} to my ChartView.
In the config the essentials:
series with type: 'ohlc' and data: [[1,2,3,4],[2,3,4,5]] inside.
In options, no arguments are required, I left it as options='' in the ChartView.
Don't forget to add stock={true} in ChartView
My code, basic example:
import React, {Component} from 'react';
import {View} from 'react-native';
import ChartView from 'react-native-highcharts';
class OHLC extends React.Component {
constructor(props) {
super(props);
}
render() {
var Highcharts='Highcharts';
var conf={
chart: {
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
type: 'ohlc',
name: 'Random data',
/*Open, high,low,close values in a two dimensional array(two days)*/
data: [[1,2,3,4],[2,3,4,5]],
}]
};
return (
<View style={{borderRadius: 4, marginTop: 30,}}>
<ChartView style={{height:500}} config={conf} javaScriptEnabled={true} domStorageEnabled={true} originWhitelist={['']} stock={true} options=''></ChartView>
</View>
);
}
}

VictoryScatter chart doesn't render dataComponent inside of chart area in React Native

I am trying to build a chart (day x hour of the day) and show an image at every "point" using victory-chart component. I played a lot on the website with the following component
https://formidable.com/open-source/victory/gallery/brush-zoom/ and got it to what I want with the code below, replacing only the tags with the React Native and with View. But when I try to use it into my React Native app, the "cats" are not being printed within the chart area, as can be seen on the image below. Am I doing something wrong?
class CatPoint extends React.Component {
render() {
const {x, y, datum} = this.props; // VictoryScatter supplies x, y and datum
const cat = datum._y >= 0 ? "😻" : "😹";
return (
<text x={x} y={y} fontSize={30}>
{cat}
</text>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
zoomDomain: {
y: [new Date(1982, 1, 1), new Date(1982, 1, 8)],
x: [6, 15]
}
};
}
handleZoom(domain) {
this.setState({ zoomDomain: domain });
}
render() {
return (
<div>
<VictoryChart
responsive={true}
width={470}
height={600}
containerComponent={
<VictoryZoomContainer
zoomDimension="y"
zoomDomain={this.state.zoomDomain}
onZoomDomainChange={this.handleZoom.bind(this)}
/>
}
>
<VictoryAxis dependentAxis crossAxis
orientation="left"
scale={{ y: "time" }}
/>
<VictoryAxis crossAxis
orientation="top"
domain={{ x: [0, 24] }}
style={{ tickLabels: { angle: -60 } }}
tickFormat={[
"0AM",
"1AM",
"2AM",
"3AM",
"4AM",
"5AM",
"6AM",
"7AM",
"8AM",
"9AM",
"10AM",
"11AM",
"12AM",
"1PM",
"2PM",
"3PM",
"4PM",
"5PM",
"6PM",
"7PM",
"8PM",
"9PM",
"10PM",
"11PM"
]}
/>
<VictoryScatter
style={{
data: { stroke: "tomato" }
}}
dataComponent={<CatPoint/>}
data={[
{ a: 8.10, b: new Date(1982, 1, 1) },
{ a: 10.50, b: new Date(1982, 1, 1) },
{ a: 12.45, b: new Date(1982, 1, 1) },
{ a: 15.30, b: new Date(1982, 1, 1) },
{ a: 17.22, b: new Date(1982, 1, 1) },
{ a: 19.12, b: new Date(1982, 1, 1) }
]}
x="a"
y="b"
/>
<VictoryScatter
style={{
data: { stroke: "tomato" }
}}
dataComponent={<CatPoint/>}
data={[
{ a: 8.30, b: new Date(1982, 1, 1) },
{ a: 11.50, b: new Date(1982, 1, 1) },
{ a: 13.45, b: new Date(1982, 1, 1) },
{ a: 16.30, b: new Date(1982, 1, 1) },
{ a: 17.32, b: new Date(1982, 1, 1) },
{ a: 18.12, b: new Date(1982, 1, 1) }
]}
x="a"
y="b"
/>
<VictoryScatter
style={{
data: { stroke: "tomato" }
}}
dataComponent={<CatPoint/>}
data={[
{ a: 8.10, b: new Date(1982, 1, 4) },
{ a: 10.50, b: new Date(1982, 1, 4) },
{ a: 12.45, b: new Date(1982, 1, 4) },
{ a: 15.30, b: new Date(1982, 1, 4) },
{ a: 17.22, b: new Date(1982, 1, 4) },
{ a: 19.12, b: new Date(1982, 1, 4) }
]}
x="a"
y="b"
/>
</VictoryChart>
</div>
I figured out what was the problem. In the CatPoint component, I was using the tag from React Native, and since I was inside of a "svg" component, I should have used the Text tag from it, like the example on the line below. :)
import { Text } from "react-native-svg";