Why would react-chartjs-2 not be able to see the data it needs to render? - react-chartjs-2

Thanks for any tips and or help! I've hit a wall here trying to get a chart to render. I've reverted to testing a very simple approach (code below) and I am still getting the following error:
TypeError: Cannot read properties of undefined (reading 'map')
I can log the data being set from the useEffect call, but I cant understand why its not making it into the Line graph. From the debugger (on utils.ts) I can see that (currentData = {labels: undefined, datasets: Array(0)}) and nextDatasets = undefined.
I'm starting to wonder if there is some version mismatch somewhere, anyways thanks for any ideas!
import React, { useState, useEffect } from "react";
import {Line} from "react-chartjs-2";
function Graph() {
const myLabels = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];
const [data, setData] = useState({});
useEffect(() => {
setData({
labels: myLabels,
datasets: [
{
label: 'The Level',
data: [21, 53, 65, 12, 32]
},
]
});
}, [])
console.log(data.datasets);
return(
<div style={{height: "500px", width: "500px"}}>
<Line data={data} />
</div>
)}
export default Graph;
The following version are in use:
"react": "^17.0.2" with
"chart.js": "^3.6.2",
"react-chartjs-2": "^4.0.0"

After some reading... I re-visited my approach and came up with the following, I'm not sure this is the proper way to go about things, still learning so if anyone has any helpful comments they'd be welcomed!
I'm not sure I completely understand at this point, but I think that the main problem I had was related to the useEffect() being used to build the data for the graph, as opposed to maybe effect the graph once it's there.
import React from "react";
import { useState } from "react";
import 'chart.js/auto';
import { Chart } from 'react-chartjs-2';
function Graph() {
const [chartData, setChartData] = useData();
return(
<div style={{height: "500px", width: "500px"}}>
<Chart type='line' data={chartData} />
</div>
)
}
export default Graph;
const useData = ( data = {} ) => {
const [state, setState] = useState(data);
data = {
labels: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'],
datasets: [
{
label: 'The Level',
data: [21, 53, 65, 12, 32]
},
]
}
return [data]
}

By default data is blank, that's why it gives an error so just you have to ensure that if data is available then you can draw the line chart.
Just change one line of code: {data.datasets ? <Line data={data} /> : ""}
import React, { useState, useEffect } from "react";
import { Line } from "react-chartjs-2";
function Graph() {
const myLabels = ["monday", "tuesday", "wednesday", "thursday", "friday"];
const [data, setData] = useState({});
useEffect(() => {
setData({
labels: myLabels,
datasets: [
{
label: "The Level",
data: [21, 53, 65, 12, 32]
}
]
});
}, []);
console.log(data.datasets);
return (
<div style={{ height: "500px", width: "500px" }}>
{data.datasets ? <Line data={data} /> : ""}
</div>
);
}
export default Graph;

Related

useContext() returns undefined values -

I have a context file and state file for Products. when I try to use that context in products component it is returning undefined values
productContext.js
import { createContext } from "react";
const ProductContext = createContext();
export default ProductContext;
ProductState.js
import ProductContext from './productContext';
import { useState } from 'react';
const ProductState = (props) => {
const productsInitial = [
{
"_id": "63a4cc857f40d0063116be5f",
"user": "63a4cbfd7f40d0063116be5d",
"title": "Cassava",
"description": "On-demand sand castle construction expertise.",
"imgURL": "null",
"price": "30",
"__v": 0
},
{
"_id": "63a4ccad7f40d0063116be69",
"user": "63a4cbfd7f40d0063116be5d",
"title": "Soyabeans",
"description": "On-demand sand castle construction expertise.",
"imgURL": "null",
"price": "30",
"__v": 0
}
]
const [products, setProducts] = useState(productsInitial);
// console.log(products);
return (
<>
<ProductContext.Provider value={{ products, setProducts }}>
{props.children}
</ProductContext.Provider>
</>
)
}
export default ProductState;
ProductComponent.js (react component)
import React, { useContext } from 'react';
import ProductContext from '../context/products/productContext';
import ProductItems from './ProductItems';
console.log(ProductContext);
const ProductComponent = () => {
const context = useContext(ProductContext);
const { products, setProducts } = context;
return (
<>
<div className="col-lg-4 ">
{products.map((product) => {
return <ProductItems product={products} />
})}
</div>
</>
)
}
export default ProductComponent;
the line
const context = useContext(ProductContext);
in Products.js Component is returning undefined value because ProductContext is returning undefined
Component that use the context must be wrapped using ProductState component
If you don't know where to add ProductState you can add in your entry point file.
root.render((
<ProductState>
<App />
</ProductState>
))
You can simplify the object destructuring
const { products, setProducts } = useContext(ProductContext);

Not able fetch the right output because of the parsing error

import logo from "./logo.svg";
import "./App.css";
import Navbar from "./Components/Navbar";
import ProductList from "./Components/ProductList";
import React, { useState } from "react";
function App() {
const productList = [
{
price: 9999,
name: "IPhone 10S Max",
quantity: 0,
},
{
price: 999,
name: "Redmi Note 10S Max",
quantity: 0,
},
];
let [productList , setProductList] = useState(productList);
const incrementQuantity = (index) => {
let newProductList = [...productList];
newProductList[index].quantity++;
setProductList(newProductList);
};
const decrementQuantity = (index) => {
let newProductList = [...productList];
newProductList[index].quantity > 0
? newProductList[index].quantity--
: (newProductList[index].quantity = 0);
setProductList(newProductList);
};
return (
<>
<Navbar />
<main className="container mt-5">
<ProductList
productList={productList}
incrementQuantity={incrementQuantity}
decrementQuantity={decrementQuantity}
/>
</main>
{/*<Footer/>*/}
</>
);
}
export default App;
**Line 21:7: Parsing error: Identifier 'productList' has already been declared. (21:7)**
Not able fetch the right output because of the parsing error.
Your state name of the value is the same like the object name:
//try to name it smth like initialProductList and pass it to useState(initalProductList)
const productList = [
{
price: 9999,
name: "IPhone 10S Max",
quantity: 0,
},
{
price: 999,
name: "Redmi Note 10S Max",
quantity: 0,
},
];
let [productList , setProductList] = useState(productList);
Also,
useState() shuld be defind with const like so:
const [productList , setProductList] = useState(productList);

How to set prop data for chart.js in React?

I'm trying to fetch data from a SQL-database and show that data on a chart.js, but I'm getting this error:
Warning: Failed prop type: Invalid prop data supplied to ChartComponent.
My code looks like this:
import React, {Component} from 'react';
import {Line} from 'react-chartjs-2';
class MinData extends Component{
constructor(){
super();
this.state = {
data: {
labels: [],
datasets: []
}
};
}
componentDidMount(){
fetch('http://localhost:4000/api/myData?limit=6')
.then (results =>{
return results.json();
}).then(data => {
let receivedData = data.map((datapost) => {
return(
{
data: {
labels: datapost.timestamp,
datasets: datapost.temp_0
}
}
)
})
this.setState({data: receivedData}, function(){
console.log(this.state.data);
});
})
}
render(){
return(
<div className="enContainer">
<Line
data={this.state.data}
options={{
title:{
display: true,
text: 'Fladan mätpunkt',
fontSize: 25
}
}}
/>
</div>
)
}
}
export default MinData;
The idea is to set state of data with the fetched data.
I'm running out of ideas, but I guess there's something wrong with the way I return data from my map function.
UPDATE:
This is what I receive in Postman when doing the same request with limit set to receive two objects:
[
{
"timestamp": "2019-01-17T18:14:20.000Z",
"battery": 5.094,
"temp_0": 23.375,
"temp_10": 19.125,
"temp_20": 19,
"temp_30": 18.812,
"temp_40": 18.562,
"temp_50": 18.625,
"temp_60": 18.688,
"temp_70": 18.688,
"temp_80": 18.188,
"temp_90": 19,
"temp_100": 18.75,
"temp_110": 18.625,
"temp_120": 18.5
},
{
"timestamp": "2019-01-17T18:17:25.000Z",
"battery": 5.104,
"temp_0": 23.375,
"temp_10": 19.125,
"temp_20": 19,
"temp_30": 18.812,
"temp_40": 18.562,
"temp_50": 18.688,
"temp_60": 18.75,
"temp_70": 18.688,
"temp_80": 18.188,
"temp_90": 19,
"temp_100": 18.75,
"temp_110": 18.625,
"temp_120": 18.5
}
]
You need to check if data is present in this.state.data.labels before calling Line component. Render method would have run before componentDidMount gets a chance to return and call api therefore empty data is passed and passed to Line component.
{
this.state.data.labels.length && <Line
data={this.state.data}
options={{
title: {
display: true,
text: 'Fladan mätpunkt',
fontSize: 25
}
}}
/>
}
State data should have following structure:
{
labels: ['First', 'Second'],
datasets: [
{
label: 'My First dataset',
data: [65, 59, 80, 81, 56, 55, 40],
},
{
label: 'My Second dataset',
data: [28, 48, 40, 19, 86, 27, 90],
},
]
}

Having issues using axios to handle my JSON data

I am trying to setState from this data,
var axios = require('axios');
import Trails from './trails';
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
trails: []
}
}
componentWillMount() {
axios
.get('https://www.mtbproject.com/data/get-trails-by-id?ids=2081068,830442%208013961&key=(API-KEY)')
.then(response => response.data)
.then(trails => this.setState({trails}));
}
which looks like this:
{
"trails": [
{
"id": 2081068,
"name": "San Dieguito River Park - Bernardo Bay\/ Piedras Pintadas Trail",
"type": "Featured Ride",
"summary": "Sweet little loop of singletrack trails.",
"difficulty": "blue",
"stars": 3.6,
"starVotes": 24,
"location": "Escondido, California",
"url": "https:\/\/www.mtbproject.com\/trail\/2081068\/san-dieguito-river-park-bernardo-bay-piedras-pintadas-trail",
"imgSqSmall": "https:\/\/cdn-files.apstatic.com\/mtb\/2148715_sqsmall_1372258680.jpg",
"imgSmall": "https:\/\/cdn-files.apstatic.com\/mtb\/2148715_small_1372258680.jpg",
"imgSmallMed": "https:\/\/cdn-files.apstatic.com\/mtb\/2148715_smallMed_1372258680.jpg",
"imgMedium": "https:\/\/cdn-files.apstatic.com\/mtb\/2148715_medium_1372258680.jpg",
"length": 8.2,
"ascent": 570,
"descent": -567,
"high": 488,
"low": 317,
"longitude": -117.0766,
"latitude": 33.0512,
"conditionStatus": "All Clear",
"conditionDetails": "Dry",
"conditionDate": "2018-09-11 09:12:17"
}
],
"success": 1
}
Then I am trying to map it like this:
render() {
return (
<div className='App'>
<div className="container">
<div className="jumbotron">
<h4>Mtb</h4>
<p>Trails:</p>
</div>
{this.state.trails.map(trail => (
<Trails key={trail.id}
conditions={trail.conditionDetails}
/>
))
}
</div>
</div>
);
}
}
I then get an error saying that my map method is not a function. Can someone point out what I am doing wrong?
When I console.log my state it appears that it is not being set, might this be the issue and be the explanation for why it is not working?
You are setting trails to be the entire data object you get in response to your request. Use the trails property of the data object instead.
componentWillMount() {
axios
.get('https://www.mtbproject.com/data/get-trails-by-id?ids=2081068,830442%208013961&key=(API-KEY)')
.then(response => this.setState({ trails: response.data.trails }));
}

Realm-js: Cannot access realm that has been closed

Realm keeps throwing this error in a simple use case:
Cannot access realm that has been closed
My files:
RealmExample.js
import Realm from 'realm';
class Item {}
Item.schema = {
name: 'Item',
properties: {
name: 'string',
date: 'date',
id: 'string'
},
};
export default new Realm({schema: [Item]});
app.js
//My imports
export default class App extends Component<{}> {
render() {
return (
<RealmProvider realm={realm}>
<ConnectedExample />
</RealmProvider>
);
}
}
ConnectedExample.js
import React, { Component } from 'react';
import {
Text,
ScrollView,
TouchableOpacity,
View,
StyleSheet,
} from 'react-native';
import uuid from 'uuid';
import { connectRealm } from 'react-native-realm';
import ConnectedExampleItem from './ConnectedExampleItem';
const styles = StyleSheet.create({
screen: {
paddingTop: 20,
paddingHorizontal: 10,
backgroundColor: '#2a2a2a',
flex: 1,
},
add: {
height: 44,
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: 10,
backgroundColor: '#1a1a1a',
},
addText: {
color: 'white',
},
});
class ConnectedExample extends Component {
count = 0;
onPressAddItem = () => {
const { realm } = this.props;
realm.write(() => {
realm.create('Item', {
name: this.count.toString(),
date: new Date(),
id: uuid.v4(),
});
this.count++;
});
};
render() {
return (
<View style={styles.screen}>
<TouchableOpacity onPress={this.onPressAddItem} style={styles.add}>
<Text style={styles.addText}>Add Item</Text>
</TouchableOpacity>
<ScrollView>
{this.props.items.map((item) => (
<View key={item.id}>
<ConnectedExampleItem id={item.id} />
</View>
))}
</ScrollView>
</View>
);
}
}
export default connectRealm(ConnectedExample, {
schemas: ['Item'],
mapToProps(results, realm) {
return {
realm,
items: results.items.sorted('date') || [],
};
},
});
ConnectedExampleItem.js
import React, {
Component,
PropTypes,
} from 'react';
import {
StyleSheet,
TouchableOpacity,
Text,
} from 'react-native';
import { connectRealm } from 'react-native-realm';
const styles = StyleSheet.create({
item: {
height: 44,
justifyContent: 'center',
paddingHorizontal: 10,
marginTop: 10,
backgroundColor: 'cyan',
},
});
class ConnectedExampleItem extends Component {
onPressRemoveItem = (item) => {
const { realm } = this.props;
realm.write(() => {
realm.delete(item);
});
};
render() {
return (
<TouchableOpacity
onPress={() => this.onPressRemoveItem(this.props.item)}
style={styles.item}
>
<Text>{this.props.item.name}</Text>
</TouchableOpacity>
);
}
}
export default connectRealm(ConnectedExampleItem, {
schemas: ['Item'],
mapToProps(results, realm, ownProps) {
return {
realm,
item: results.items.find(item => item.id === ownProps.id),
};
},
});
The strange thing is that when running this code on my project I run into the Cannot access realm that has been closed (I haven't instantiated Realm anywhere else), however, if I run the example in the react-native-realm repo, it runs fine.
Also, the introduction example on the Realm documentation page runs fine as well.
What could be the issue?
Thank you.
PS: Running on React-native 0.51, Android device 6.0.

Resources