I'm new to web dev and currently trying to develop a dashboard.
My api data returns like this:
{
'ada': {'available': '45', 'profit': '-0.5'},
'eth':{'available': '2', 'profit': '5'}
}
and the code that gets the data is
useEffect(() => {
const fetchAPI = async() => {
const resp = await httpClient.get("//localhost:5000/dashboard")
data = resp.data
console.log(data)
if(data){
keys_list = Object.keys(data).map((crypto) => crypto)
data_list = Object.values(data).map((crypto) => crypto.current)
setChartData({
labels: keys_list,
datasets: [
{
label: 'Price in KRW',
data: data_list,
backgroundColor: [
"#ffbb11",
"#ecf0f1",
"#50AF95",
"Blue",
"Purple",
"Red",
"Green"
]
}
]
});
}
};
fetchAPI()
}, []);
const [chartData, setChartData] = useState({datasets: []})
I would like to make a sort of table that just returns the different values of each keys.
token available profit
ada 45 -0.5
eth 2 5
Any insights would be highly appreciated
Related
I have an array of objects response that comes from API. I don't have access to the API to be able to change it.
data = [
{"label": "Group 1", "value": "1"},
{"label": "Group 2", "value": "2"},
{"label": "Group 3", "value": "3"}
]
I need to display the data, so the label says Post to ${label}.
Can I inject the 'Post to ' string somehow? Do I make a new array from my response?
Here's how I'm fetching the data:
const [pickerData, setPickerData] = React.useState<{ label: string; value: string }[]>([]);
const fetchPickerData = React.useCallback(async () => {
const response = await getPostLocations();
if (!response) return;
if (response) {
setPickerData(response);
}
}, []);
React.useEffect(() => {
fetchPickerData().catch(console.error);
}, [fetchPickerData]);```
and my data is then loaded into a picker:
<Picker
items={pickerData}
value={pickerItem}
onValueChange={(pickerItem) => setPickerItem(pickerItem)}
/>
Things I already tried is trying to inject string into value like value={()=>{`Post to ${pickerItem}`}}, or the same in the setPickerItem in onValueChange but that didn't work
You can use Array#map() to create a new array from the response in the format you prefer:
const fetchPickerData = React.useCallback(async () => {
const response = await getPostLocations();
if (!response) return;
if (response) {
const formattedResponse = response.map(
({ label, value }) => ({ 'label': `Post to ${label}`, value })
)
setPickerData(formattedResponse);
}
}, []);
Try it like this
const [pickerData, setPickerData] = React.useState<{ label: string; value: string }[]>([]);
const [apiData, setApiData] = React.useState<{ label: string; value: string }[]>([]);
const fetchPickerData = React.useCallback(async () => {
const response = await getPostLocations();
if (!response) return;
if (response) {
setApiData(response);
}
}, []);
React.useEffect(() => {
fetchPickerData().catch(console.error);
}, [fetchPickerData]);
React.useEffect(() => {
if (apiData.length > 0) {
let Temp = [];
apiData.forEach((item) => {
let newItem = {
...item,
label: `Post to ${item.label}`
};
Temp.push(newItem);
});
setPickerData(Temp);
}
}, [apiData]);
Im kind of new to web dev and stuck at a problem when trying to visualize data using a doughnut chart from chartjs.
useEffect(() => {
const fetchAPI = async() => {
const resp = await httpClient.get("//localhost:5000/dashboard")
const data = resp.data
// console.log("From fetchapi", Object.values(data).map((crypto) => crypto.current))
const keys_list = Object.keys(data).map((crypto) => crypto)
const data_list = Object.values(data).map((crypto) => crypto.current)
//console.log(data_list)
setChartData({
labels: keys_list,
datasets: [
{
label: 'Price in KRW',
data: data_list,
backgroundColor: [
"#ffbb11",
"#ecf0f1",
"#50AF95"
]
}
]
});
};
fetchAPI()
}, []);
const [chartData, setChartData] = useState({})
return(
<div><Doughnut data = {chartData}</div>
)
data here looks like this
{'eth': {'available': '0.5', 'current': '890'}, 'ada': {'available': '43.9', 'current': '24'}}
so I'm trying to put data as data.current, here would be ['890', '24'] and the labels as ['eth', 'ada']
However I'm getting an Uncaught TypeError: Cannot read properties of undefined (reading 'map') error.
Any help would be highly appreciated!
Your data is asynchronous. On page load, data is undefined until your data arrives. Add interrogation point like this, which means to make a map if the data exists
useEffect(() => {
const fetchAPI = async() => {
const resp = await httpClient.get("//localhost:5000/dashboard")
const data = resp.data
// console.log("From fetchapi", Object.values(data).map((crypto) => crypto.current))
if(data){
const keys_list = Object.keys(data).map((crypto) => crypto)
const data_list = Object.values(data).map((crypto) => crypto.current)
//console.log(data_list)
setChartData({
labels: keys_list,
datasets: [
{
label: 'Price in KRW',
data: data_list,
backgroundColor: [
"#ffbb11",
"#ecf0f1",
"#50AF95"
]
}
]
});
}
};
fetchAPI()
}, []);
I'm trying to remove objects in the array from the end in sequence So I tried to use pop and splice
but for some reason, when I use the pop function then all the objects are removed, and got an error :
is not a function and when I use the splice function then all the objects are removed
here is my code :
const [appendChartData, setAppendChartData] = useState(chartData.datasets);
const appendAxis = e => {
e.preventDefault();
setAppendChartData([...appendChartData, AppendData]);
};
const deleteAxis = () => {
setAppendChartData(appendChartData.splice(-1, 1));
/// setAppendChartData(appendChartData.pop());
};
chartData.datasets
export let chartData =[ {
labels: defaultLabels,
datasets: [
{
label: "dataSetting",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
},]
AppendData
export let AppendData = {
label: "dataSetting",
data: defaultDatas,
backgroundColor: defaultBackgroundColor,
};
so I'd like to remove the array in sequence from the end
The way you used the state is wrong. You should use the chartData as state:
const [appendChartData, setAppendChartData] = useState(chartData);
const appendAxis = e => {
e.preventDefault();
setAppendChartData({
...appendChartData,
datasets: [
...appendChartData.datasets,
AppendData
]
});
};
const deleteAxis = () => {
setAppendChartData({
...appendChartData,
datasets: appendChartData.datasets.splice(-1, 1)
});
};
Also, be careful about your chartData since I saw that you defined it as an array of objects. If that's true then you must consider it in the code above.
I am able to fetch data what url, but the thing is the url is divided into couple of arrays and I need to fetch data and connect them.
Example:
{
"array1": [
{ "data1": {"name": "Name", "phone": "Phone"}}
]
"array2" : [
{ "data2": { "color": "Color", "car": "Car" } }
]
}
Data hooks :
const userInfo = "URL";
const [userData, setUserData] = useState([]);
useEffect(() => {
getUserInfo();
}, []);
const getUserInfo = async () => {
const response = await fetch(UserInfo);
const jsonData = await response.json();
setUserData(jsonData);
};
Fetch data:
{ userData.data && userData.array1.map((array1, index) =>
<li key={"index" + index}
<h5>{array1.data1.name} </h5>
</li>
)}
I need to connect name from array1 with color from array2, but I can not find the way to do it.
Expected Output : list of data
If you can get those two arrays then you can use this to combine them:
const getUserInfo = async () => {
const response = await fetch(UserInfo);
const jsonData = await response.json();
// this assumes `jsonData` in an object with keys `array1` and `array2`
// if this is not the case, change `jsonData` below to the location of
// those two arrays
const { array1, array2 } = jsonData;
const combinedArray = array1.map(({ data1 }, i) => ({
...data1,
...array2[i].data2 // assumes there is always a corresponding index in array 2
}));
// combinedArray will look like [ { name: 'Name', phone: 'Phone', color: 'Color', car: 'Car' } ]
setUserData(combinedArray);
};
]
My query was taking more than 2 mins to execute, henceforth it was getting timeout in browser. So now I have break the query and now running as a separate APIs which is helpful, but now I don't know how to handle these three requests so that it can render the data.
Note: The API's data are getting stored in the State component of react, here it is "Data".
Now I have a logic but can anyone give me a direction how to implement it.
Logic: Before storing the result of API's directly into state component, we can store it into different array, then we can iterate through this array for the use of pie chart then this data can be stored into the state component which can be used to render the pie chart in "Render" function.
Here the I am making three different API calls at the same time and storing it, here the result of the API's are directly been stored in the state component:
componentDidMount() {
Promise.all([
fetch("http://localhost:4000/api/EMEA/E_claimQuarter"),
fetch("http://localhost:4000/api/EMEA/E_claimQuarter1"),
fetch("http://localhost:4000/api/EMEA/E_claimQuarter2")
])
.then(([res1, res2, res3]) =>
Promise.all([res1.json(), res2.json(), res3.json()]))
.then(([data1, data2, data3]) =>
this.setState({
// Data: data1, data2, data3,
Data: {
labels: [
"FY19 Q1[NOV-JAN]",
"FY19 Q2[FEB-APR]",
"FY18 Q3[SEP-NOV]"
],
datasets: [
{
label: "",
data: data1,
backgroundColor: [
"rgba(255,105,145,0.6)",
"rgba(155,100,210,0.6)",
"rgb(63, 191, 191)"
]
}
]
}
})
);
}
This is how you handle the data form API and loop through it then render this data for the various charts which is in my case is Pie Chart:
ComponentDidMount() {
axios.get(`http://localhost:4000/api/APJ/A_claimQuarter`)
***************************************************************
.then(res => {
const claims = res.data;
let claim = [];
claims.forEach(element => {
claim.push(element.CNT1);
});
********************************************************************
this.setState({
Data: {
labels: ['FY19 Q1[NOV-JAN]','FY19 Q2[FEB-APR]','FY18[SEP-NOV]'],
datasets:[
{
label:'',
data: claim ,
backgroundColor:[
'rgba(255,105,145,0.6)',
'rgba(155,100,210,0.6)',
'rgb(63, 191, 191)'
]
}
]
}
});
})
}
I have made some modifications and now it is working fine for me, if anyone want the answer you can look at mine, it is 100% working:
constructor(props) {
super(props);
this.state = {
Data: []
};
}
componentDidMount() {
Promise.all([
fetch("http://localhost:4000/api/EMEA/E_claimQuarter"),
fetch("http://localhost:4000/api/EMEA/E_claimQuarter1"),
fetch("http://localhost:4000/api/EMEA/E_claimQuarter2")
])
.then(([res1, res2, res3]) => Promise.all([res1.json(), res2.json(), res3.json()]))
.then(([data1, data2, data3]) =>
{
console.log(typeof(data1));
const array = [...data1, ...data2, ...data3];
// const A = JSON.strigify(array);
console.log('hi');
console.log(array);
console.log(data1);
// console.log(A);
let claim = [];
array.forEach(element => {
claim.push(element.COUNT);
});
console.log(claim);
this.setState({
// Data: data1, data2, data3,
Data: {
labels: [
"FY19 Q1[NOV-JAN]",
"FY19 Q2[FEB-APR]",
"FY18 Q3[SEP-NOV]"
],
datasets: [
{
label: "",
data: claim,
backgroundColor: [
"rgba(255,105,145,0.6)",
"rgba(155,100,210,0.6)",
"rgb(63, 191, 191)"
]
}
]
}
})
});
}
Based on OP's own answer, here's a more generalised solution :
componentDidMount(graphData) {
return Promise.all(graphData.map(dataObj => dataObj.url))
.then(results => Promise.all(results.map(res => res.json())))
.then(results => this.setState({
'Data': {
'labels': graphData.map(dataObj => dataObj.label),
'datasets': [
{
'label': '',
'data': results.reduce((prev, next) => prev.concat(next), []),
'backgroundColor': graphData.map(dataObj => dataObj.bgColor)
}
]
}
}));
}
As you see, Array methods .map() and .reduce() make for some nice compact code.
Call as follows:
var quartersData = [
{ 'url':'http://localhost:4000/api/EMEA/E_claimQuarter', 'label':'FY19 Q1[NOV-JAN]', 'bgColor':'rgba(255,105,145,0.6)' },
{ 'url':'http://localhost:4000/api/EMEA/E_claimQuarter1', 'label':'FY19 Q2[FEB-APR]', 'bgColor':'rgba(155,100,210,0.6)' },
{ 'url':'http://localhost:4000/api/EMEA/E_claimQuarter2', 'label':'FY18 Q3[SEP-NOV]', 'bgColor':'rgb(63, 191, 191)' }
];
componentDidMount(quartersData)
.then(() => {
console.log('complete');
});