AJax issue while loading google chart in react - reactjs

I am trying to use Google chart in React. I read the data from the database and use hook(useState) to save the data. But I can't load the google chart when I fetch the data. I guess it is Ajax problem. I have tried to copy the data that I read from console.log and paste it, it works, so it is not the data format issue.
//inistialise
const [v1, setV1] = useState(['x','sensor'],[0,0])
//define data value
const data = v1;
//define option for Chart
const options = {
title: "Box Office Earnings in First Two Weeks of Opening",
subtitle: "in millions of dollars (USD)",
interpolateNulls: true
};
//fetch data from database and change the data format
async function getAllSensorProfile(sensorIdList, sensorSubId, starttime, endtime) {
sensorIdList = JSON.stringify(sensorIdList)
await deviceService.GetTimeSeriesListBySensorIdListTimeRange(sensorIdList, sensorSubId, starttime, endtime).then(
(result) => {
var time = []
var _v1 = [['x', 'dogs']]
result.map((str) => (
str[1] = parseFloat(str[1])
))
_v1 = _v1.concat(result)
setV1(JSON.stringify(_v1))
console.log(v1)
},
error => {
console.log(error)
}
)
}
<Chart
chartType="LineChart"
data={this.state.data}
options={options}
width={"70%"}
height={"400px"}
/>

I have fixed it! OMG I had this issue for a few days but could not fix it. Now I find the problem!
So the problem is, setV1(JSON.stringfy(_v1)) is converting v1 to be a string, however, in <Chart>, data={data} only accept object, not a string.
So, I simply just change it to setV1(_v1) then it works!

Related

React - save components visualization to JSON and read it back

Imagine I have a hierarchy of react components, e.g. meals of the day
|------- breakfast --------|
| Meal1_image.png banana |
| Meal2_image.png porridge|
|------- lunch-------------|
| Meal3_image.png toast |
| Meal4_image.png apple |
I can add meals to a meal group (e.g. to the lunch group), I can add more lunch groups (e.g. midday snack) and so on.. it's a variable list of components and I give the user the ability to add meals and meal groups with '+' buttons, or to delete them and so on.
How would I go to save these in a text json and to read them back?
I read about "serializing react components" but maybe I don't need all of that stuff, I would just need to save a json like
{
"breakfast": {
{"food": "banana", "image": "Meal1_image.png"},
{"food": "porridge", "image": "Meal2_image.png"},
},
"lunch" : ... and so on ...
}
is there any simple way to achieve this or should I just go with components serialization with things like https://github.com/zasource-dev/React-Serialize ?
Question is basically too wide, but anyway, just split your task by subtasks.
Design the data models you are going to work with. Create a prototype of it, try to render it as is. Regarding your prototype - that is not valid js object, so i changed it a bit in my example. Note - for .map methods you need to use unique keys.
Figure out what will be the best place to keep your data (in state). You can store it in some component, you can store it in context and add all the needed methods to it and pass them down to your components. I did everything in a component for simplicity of example.
Add download/upload/parsing functions and wire everything up.
If I got your question right - you want each Client to be able to download and upload the Data to a local JSON file on Client, so no server interaction.
const { useState } = React;
function download(content, mimeType, filename) {
const a = document.createElement("a");
const blob = new Blob([content], { type: mimeType });
const url = URL.createObjectURL(blob);
a.setAttribute("href", url);
a.setAttribute("download", filename);
a.click();
}
function upload(event, callback) {
const input = event.target;
const reader = new FileReader();
reader.onload = function () {
const text = reader.result;
callback(text);
};
reader.readAsText(input.files[0]);
}
const DEFAULT_DATA = {
breakfast: [
{ food: "banana", image: "Meal1_image.png" },
{ food: "porridge", image: "Meal2_image.png" }
],
lunch: [{ food: "banana", image: "Meal1_image.png" }]
};
function App() {
const [data, setData] = useState(DEFAULT_DATA);
const onDownloadClick = (e) => {
download(JSON.stringify(data), "application/json", "file1.json");
};
const onUpload = (e) => {
upload(e, (text) => setData(JSON.parse(text)));
};
return (
<div className="App">
{Object.entries(data).map(([section, items]) => (
<div key={section}>
<p>{section}</p>
<ul>
{items.map((item) => (
<li key={item.food}>
<p>{item.food}</p>
</li>
))}
</ul>
</div>
))}
<button onClick={onDownloadClick} type="button">
Download JSON
</button>
<input type="file" accept="application/json" onChange={onUpload} />
</div>
);
}
// v18.x+
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>
How to test - Download JSON file, open it and change something in it, like "banana" to "banana111", save, upload the file back and observe the updated values.
Not sure what is the plan about Images, but in worst case - you can store images in JSON as base64 strings.
If you mean physical saving in a file, then you need to have node js to access the file system of your phone or PC, your server:
// file system module to perform file operations
const fs = require('fs');
// json data
var jsonData = '{"persons":[{"name":"John","city":"New York"},{"name":"Phil","city":"Ohio"}]}';
// parse json
var jsonObj = JSON.parse(jsonData);
console.log(jsonObj);
// stringify JSON Object
var jsonContent = JSON.stringify(jsonObj);
console.log(jsonContent);
fs.writeFile("output.json", jsonContent, 'utf8', function (err) {
if (err) {
console.log("An error occured while writing JSON Object to File.");
return console.log(err);
}
console.log("JSON file has been saved.");
});
If we are talking about transformation for axios request, then you need to use the following javascript methods JSON.stringify() for json transformation and JSON.parse() for reading to transformation in javascript.
If you just want to transform the object in the hook state, this is also fine.

How to filter the data from an API in a ethical way? Im using react JS

it work properly but I refresh the page i get this error
"TypeError: Cannot read properties of undefined"
here is my code
for fetching the data from API
useEffect(() => {
let isSuscribe = true
axios.get(myLocalAPI)
.then(res =>
{
if (isSuscribe) {
setData(res.data)
}
}
)
.catch(err => console.log(err))
return () => isSuscribe = false
})
I have a 3 Combo box for filtering the data for Year,Month and Day.
the date format on my API was this "YYYY-MM-DD"
When I filter the data of course it will show on DataGrid and also get the Total sales on within that date
to implement that this is my Code
For filter Table "Yvalue + "-" + Mvalue + "-" + Dvalue" = YYYY-MM-DD
const filter_table = () =>{
return Data.filter(
date=>date.Customer_date
.toLowerCase()
.includes(Yvalue + "-" + Mvalue + "-" + Dvalue) )
}
for filter and get the Total sales
const filter_data = () => {
return Data.filter(
date=>date.Customer_date
.toLowerCase()
.includes(Yvalue + "-" + Mvalue + "-" + Dvalue)) //Filter the data first
.map(e=>e.Customer_total) //When it true map the Total for each data
.reduce((a,b)=>a+b, 0 ) // Sum the total
}
when I Click the button and console both return funnction it work properly but when i implement this on DataGrid
<DataGrid
columns={columns}
getRowId={(rows) => rows.Customer_ID}
rows={filter_table()}
pageSize={10}
/>
<span className="featuredTitleperoBlack">{filter_data()} </span>
and I get this error
Cannot read properties of undefined
can I ask you guys please explain why I get this error and ethical way to filter the data ?
I really appreciated if there is sample code so that I learn where I was wrong
Thank you!!!
When you've just refreshed the page, you don't have the data yet - the server did not respond yet - but you're already trying to filter it.
One way to solve is to check for Data to exist. Another way is conditional chaining, like this
Data?.filter(filterFunction) // if Data is present, it will be filtered

How to change decimal character (.) to (,)

I want to change my decimal in my service or client with generic solution. I'm using .Net WebApi on my service side. And I'm using React.JS with axios on my client side. I have some values about money in my data and they all come with (.) if it's decimal. For example, totalDebtAmount = 54.69$ then I want to show it 54,69$. And for example if the value is much more than 1000, my value should be seen such as 12.456,98$. Is there any way without string.replace() because I have so many pages and I don't want to use 'replace method' for my all values time after time. May I change settings of visual studio or axios library for it? You can see my sample codes and images at below.
export const GetDebtList = (SUBSCRIBER_OID_LIST,SUBSCRIBER_INFO_OID,PAYMENT_DATE,
SuccessOperation, FailedOperation) => {
return () => {
const body = { subscriberOidList: SUBSCRIBER_OID_LIST, subscriberInfoOid:SUBSCRIBER_INFO_OID,
paymentDate:PAYMENT_DATE };
axios.post('/api/GetDebtList', body)
.then(response => {
SuccessOperation({ DEBT_LIST: response.data });
})
.catch(() => {
FailedOperation({ DEBT_LIST: null })
});
}}
Here my data and GridPanel
You have to differentiate between the visual appealing of the number and the value itself.
The value must always be formatted as a floating-point number (using .)
How you display your currency, depends on the users' locality.
I would recommend using the Intl.NumberFormat API (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) or use a currency formatting library like Dinero.js (https://github.com/dinerojs/dinero.js)
Of course, you can already do the formatting on the server-side, but I would recommend doing so on the client.
const value = 54.69;
return (
<>
{new Intl.NumberFormat('en', { style: 'currency', currency: 'USD' }).format(value)}
</>
)

How to upload image and pass in to tensorflowjs model to get prediction using reactjs?

EDIT
Using the graph model format and the updated code example, I've managed to get it to return a prediction. Issue is now it always returns 1, no matter which image I feed it, so wondering if I am not passing in the right image data?
Second EDIT: Changed the way I was passing in the img object, but still getting 1 for every image I feed it.
I have only just started looking into tensorflowjs and am using a prebuilt keras model I have been given access to. This model is a binary classifier. The model has been saved as an .h5 file and I have been asked to run it in the browser using tensorflowjs and react. Essentially I want to select an image from my local storage or an sd card and feed it to the model to get a yes or no classification.
I’ve followed the tensorflowjs docs in converting the keras model to a TF.js Layers format, but then can’t load the model. I’m getting an error about an unknown layer: RandomFlip. So I then tried converting the model to a graph model as I couldn’t find a solution to the error and thought I’d give it a try. This loaded the model but then there were more issues when feeding it the image. The shape of dict['image_tensor'] provided in model.execute(dict) must be [-1,380,380,1], but was [380, 380] . Then I searched for that and got it to resize to [-1,380,380,1] , but then it was complaining about size not being the expected, so I thought maybe I've messed up in some of the previous steps.
To convert to a graph model I used the following command: tensorflowjs_converter --input_format keras --output_format tfjs_layers_model /Users/myUser/Documents/save_at_45.h5 /Users/myUser/Documents/convert-keras-model and in my code loading it with the loadGraphModel method. Following this path has at least allowed me to load the model.
I also tried converting it to a Layers format with: tensorflowjs_converter --input_format keras --output_format tfjs_layers_model /Users/myUser/Documents/save_at_45.h5 /myUser/mariomendes/Documents/convert-keras-model and in my code loading it with the loadLayersModel. This returns the error Unknown layer: RandomFlip. I've tried searching for a solution to this, but haven't been able to find one.
Does knowing it is a .h5 file mean I should know if it needs to be converted to a tf Graph format or Layers format or is there something else that determines which format it should be converted to?
I've stored the converted model in both formats and it's weights in S3 and am getting it from there.
For my react code I have done the following:
import React, { useState, useEffect } from "react";
import "./index.css";
import * as tf from "#tensorflow/tfjs";
function ImgImporter() {
const [file, setFile] = useState(null);
const [model, setModel] = useState(null);
const [processing, setProcessing] = useState(false);
const [prediction, setPrediction] = useState(null);
const [imageLoaded, setImageLoaded] = useState(false);
function readImage(file) {
return new Promise((rs, rj) => {
const fileReader = new FileReader();
fileReader.onload = () => rs(fileReader.result);
fileReader.onerror = () => rj(fileReader.error);
fileReader.readAsDataURL(file);
});
}
async function handleImgUpload(event) {
const {
target: { files },
} = event;
const _file = files[0];
const fileData = await readImage(_file);
setFile(fileData);
setProcessing(true);
}
useEffect(() => {
async function loadModel() {
if (!model) {
const _model = await tf.loadGraphModel("/model.json");
setModel(_model);
}
}
loadModel();
});
useEffect(() => {
async function predict() {
if (imageLoaded && file) {
const imageElement = document.createElement("img");
imageElement.src = file;
imageElement.onload = async () => {
const tensor = tf.browser
.fromPixels(imageElement, 1)
.resizeNearestNeighbor([380, 380])
.expandDims()
.toFloat();
const prediction = await model.predict(tensor).data();
setPrediction(parseInt(prediction, 10));
setProcessing(false);
setImageLoaded(false);
};
}
}
predict();
}, [imageLoaded, model, file]);
return (
<div className="File-input-container">
<form className="Form">
<label htmlFor="upload-image">Upload image</label>
<input
id="image-selector"
type="file"
name="upload-image"
accept="image/*"
className="File-selector"
onChange={handleImgUpload}
disabled={!model || processing}
/>
</form>
<div className="Img-display-container">
<img
onLoad={() => {
setImageLoaded(true);
}}
alt=""
src={file}
/>
</div>
<div className="Img-processing-container">
{processing ? (
<p>Loading ...</p>
) : prediction !== null ? (
<div>
<p>{prediction === 1 ? "Yes" : "No"}</p>
</div>
) : null}
</div>
</div>
);
}
export default ImgImporter;
When I upload an image this is returning the following result in the console as the value of prediction:
dataId: {id: 195}
dtype: "float32"
id: 94
isDisposedInternal: false
kept: false
rankType: "2"
scopeId: 6
shape: (2) [1, 1]
size: 1
strides: [1]
Would be great if someone could shed some light on this or help me finding the right direction.
If you want to get the value, you can use prediction.dataSync() or its promise counterpart await prediction.data()
Regarding your second edit. You're converting the image to a float, but does the model expect a normalized float? You might need to append .div(255) or whatever normalization is needed. Please post the specs for your model.
Also, as stated by edkeveked, you can used dataSync() to get your data, but it's worth noting you could have also used arraySync too, which would maintain the returned tensor depth.
Also, I noticed you didn't do any cleanup. So your tensors will build up in GPU memory. Don't forget to dispose.
I hope these things help.

How to refresh Graph Input data in Angular 2

I am using some Graph view to view some statistic in my project.
e.g. Morish Grapgh, Pie chart graph.
I have an option like date range, so that I can specify the range of date and can fetch the data within that range and show the output graph in the front end.
The issue I am facing is at the First time I am able to see the out put while I am changing the Date range.
from the second time I am able to get the Data from the backend but after setting the new set of values to the graph Data, but the graph view is not changing because the graph is not able to refresh.
Here sample code. Please ask if any additional info needed.
<sa-morris-graph *ngIf="graphData!=null" [data]="graphData"
type="area"
[options]="{
xkey: 'x',
ykeys: ['y', 'z'],
labels: ['USER', 'New USER']
}"></sa-morris-graph>
from the Component type script file I am setting graphData
export class GAUserComponent implements OnInit{
fromDate : any ;
toDate : any ;
graphData : any = null;
dateSelected(){
this.gaService.getGaData(this.req,"/users")
.subscribe(
data => {
this.dataResponse = data;
let grData = [];
for (let data of this.dataResponse.usersByDate) {
var sample={"x": data.valueX ,"y": data.valueY , "z" : data.valueZ };
grData.push(sample);
}
this.graphData = grData;
},
err => {
console.log("Error occered : "+ err);
}
);
}
Please suggest me to solve the problem.
I guess In angular 1 there is a watch() to achieve this but in angular 2 this function is not there.
correct me If I am wrong and help me solve this
Thanks

Resources