Error "Table has no columns."
It's not returning the API data in the React-google-Charts chart and I can't find the error, anyone to help me? I already broke my head here... It's a Column chart and it's already in the required format.
default model:
export const data = [
["Element", "Density", { role: "style" }],
["Copper", 8.94, "#b87333"], // RGB value
["Silver", 10.49, "silver"], // English color name
["Gold", 19.3, "gold"],
["Blue", 21.45, "color: #0592FF"],
["Oranje", 21.45, "color: #FF494C"],
["Brown", 21.45, "color: brown"],
["Platinum", 21.45, "color: #e5e4e2"],
// CSS-style declaration
];
Returning on the console:
[
[
"Solicitante",
"Quantidade",
{
"role": "style"
}
],
[
[
"deisemorais",
18,
"#e5e4e2"
]
],
[
[
"moisesmoura",
5,
"#e5e4e2"
]
],
[
[
"elissonsilva",
7,
"#e5e4e2"
]
],
[
[
"wellingtonreis",
2,
"#e5e4e2"
]
],
[
[
"josecfilho",
2,
"#e5e4e2"
]
],
[
[
"wisleycouto",
2,
"#e5e4e2"
]
],
[
[
"laireborges",
2,
"#e5e4e2"
]
],
[
[
"marcelobento",
7,
"#e5e4e2"
]
],
[
[
"rosaniaxavier",
2,
"#e5e4e2"
]
],
[
[
"rafaelalfarone",
1,
"#e5e4e2"
]
]
]
Follow the code
import React, { useEffect, useState } from "react";
import { ColumnChart } from "./components/graficos-modelos/ColumnChart/ColumnChart";
import api from "./service/api";
const App = () => {
const [chartData, setChartData] = useState({});
useEffect(() => {
const fetchData = async () => {
try {
const response = await api();
const data = response.data;
// console.log(data);
const solicitantes = {};
data.body.forEach(element => {
const solicitante = element["SOLICITANTE"];
if (solicitante in solicitantes) {
solicitantes[solicitante] += 1;
} else {
solicitantes[solicitante] = 1;
}
});
const dataForChart = [['Solicitante', 'Quantidade', { role: "style" }]].concat(
Object.entries(solicitantes).map(([solicitante, value]) => [[ solicitante, value, "#e5e4e2" ]])
);
setChartData(dataForChart);
console.log(dataForChart);
if (dataForChart[0].length >= 2) {
setChartData(dataForChart);
} else {
console.error("Table has no columns.");
}
}catch (error) {
console.error(error);
}
};
fetchData();
}, []);
return (
<div>
<h1>Grafics in React</h1>
<ColumnChart data = {chartData} />
</div>
);
};
export default App;
if (dataForChart[0].length >= 2) {
setChartData(dataForChart);
} else {
console.error("Table has no columns.");
}
I put this snippet in the code to see if it found any errors but it did not return anything.
I have gone through the code snippet and done some refactor with the code. Please have a look on it.
Issues -
There is no body key inside data object.
Second the logic const solicitante = element['SOLICITANTE']; can be replaced to const solicitante = element[0];
import React, { useState, useEffect } from 'react';
import { Chart } from 'react-google-charts';
const ColumnChart = () => {
const data = [
['Element', 'Density', { role: 'style' }],
['Copper', 8.94, '#b87333'], // RGB value
['Silver', 10.49, 'silver'], // English color name
['Gold', 19.3, 'gold'],
['Blue', 21.45, 'color: #0592FF'],
['Oranje', 21.45, 'color: #FF494C'],
['Brown', 21.45, 'color: brown'],
['Platinum', 21.45, 'color: #e5e4e2'],
];
const [chartData, setChartData] = useState({});
useEffect(() => {
const fetchData = async () => {
try {
const solicitantes = {};
data.forEach((element) => {
const solicitante = element['SOLICITANTE'];
if (solicitante in solicitantes) {
solicitantes[solicitante] += 1;
} else {
solicitantes[solicitante] = 1;
}
});
const dataForChart = [
['Solicitante', 'Quantidade', { role: 'style' }],
].concat(
Object.entries(solicitantes).map(([solicitante, value]) => [
solicitante,
value,
'#e5e4e2',
])
);
setChartData(dataForChart);
console.log(dataForChart);
if (dataForChart[0].length >= 2) {
setChartData(dataForChart);
} else {
console.error('Table has no columns.');
}
} catch (error) {
console.error(error);
}
};
fetchData();
}, []);
return (
<div>
<Chart
chartType="ColumnChart"
width="100%"
height="400px"
data={chartData}
/>
</div>
);
};
export default ColumnChart;
Please find the image attached below which I reproduced after changes.
Hope this will help you!
Regards
Related
var json = [
{
"bbox":[
24.24112319946289,
15.165281295776367,
560.5425834655762,
457.0700454711914
],
"class":"person",
"score":0.8514186143875122
},
{
"bbox":[
291.99377059936523,
84.65291976928711,
315.9793281555176,
376.3008499145508
],
"class":"tv",
"score":0.8043261766433716
},
{
"bbox":[
296.79737091064453,
353.7140464782715,
252.2602081298828,
114.29803848266602
],
"class":"person",
"score":0.5516218543052673
}
]
Hi, I need help, I need to obtain data all 'class : person' from json above. How to do that?
Please try this
const ids = ["person"];
const data = [
{
"bbox":[
24.24112319946289,
15.165281295776367,
560.5425834655762,
457.0700454711914
],
"class":"person",
"score":0.8514186143875122
},
{
"bbox":[
291.99377059936523,
84.65291976928711,
315.9793281555176,
376.3008499145508
],
"class":"tv",
"score":0.8043261766433716
},
{
"bbox":[
296.79737091064453,
353.7140464782715,
252.2602081298828,
114.29803848266602
],
"class":"person",
"score":0.5516218543052673
}
];
const data2 = data.filter( i => ids.includes( i.class ) );
console.info( data2 );
[Updated]:
You can filter the array to get the desired object:
const person = json.filter((item) => item.class === 'person')
This will return the object having class key's value as person
[
{
"bbox":[
24.24112319946289,
15.165281295776367,
560.5425834655762,
457.0700454711914
],
"class":"person",
"score":0.8514186143875122
},{
"bbox":[
296.79737091064453,
353.7140464782715,
252.2602081298828,
114.29803848266602
],
"class":"person",
"score":0.5516218543052673
}
]
I have created this function, however is not quite right. I get this response from it:
[
{
manufacturer: [
'AUDI'
]
},
{
body_colour: {
'BLACK'
}
}
]
However what I want is:
{
manufacturer: [
'AUDI'
],
body_colour: {
'BLACK'
}
}
How can I get to this? This is what I have at the moment:
checkForQueryString() {
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
let searchParams = Object.entries(params).map(([key, value]) => {
return {
[key]: value.split(',')
}
});
return searchParams;
},
Query String: ?manufacturer=AUDI&body_colour=BLACK
Use reduce not map
const params = {
manufacturer: "AUDI",
body_colour: "BLACK"
}
let searchParams = Object.entries(params).reduce((acc, [key, value]) => {
return {
...acc,
[key]: value.split(',')
}
}, {});
console.log(searchParams)
Object.fromEntries(urlSearchParams.entries()), Object.entries(params) are not necessary.
You can use a simple forEach function to achieve the desired result as from MDN DOCS.
function checkForQueryString() {
const searchParams = new URLSearchParams(window.location.search);
var result = {};
searchParams.forEach(function(value, key) {
result[key] = value.split(',');
});
return result;
}
console.log( checkForQueryString() );
When url is http:example.com?manufacturer=audi,tesla&body_colour=black,white
the output would be
{
"manufacturer": [
"audi",
"tesla"
],
"body_colour": [
"black",
"white"
]
}
Assumin you meant by your input:
body_colour: [
'BLACK'
]
The answer can be:
let myArray = [
{
manufacturer: ['AUDI']
},
{
body_colour: ['BLACK']
}
];
let newObj = Object.assign({}, ...myArray)
You can make use of Object.fromEntries with split and map:
const str = 'manufacturer=AUDI&body_colour=BLACK';
console.log(Object.fromEntries(str.split('&').map(o=>[o.split('=')[0],[o.split('=')[1]]])));
I use this hook : react-use-scrollspy that uses an sectionRefs of useRef in array
const sectionRefs = [
useRef(null),
useRef(null),
useRef(null),
];
const activeSection = useScrollSpy({
sectionElementRefs: sectionRefs,
offsetPx: -80,
});
But I use this instead of that array of refs :
const menuItemsRef = {
home: "0",
packs: "4",
faq : "8",
projects: "2",
team : "7",
contact : "6"
}
const menuRef = useRef(Object.keys(menuItemsRef));
let menuRef2 = [];
useEffect(()=>{
menuRef2 = Object.values(menuRef.current).slice(6,12).map((item)=>
{
return { current : item }
});
console.log("menuRef " , menuRef2);
},[]);
const activeSectionNavbar = useScrollSpy({
sectionElementRefs: menuRef2,
offsetPx: -80,
});
Why it didn't work?
To clarify , my problem is to turn this :
const menuItemsRef = {
home: "0",
packs: "4",
faq : "8",
projects: "2",
team : "7",
contact : "6"
}
const menuRef = useRef(Object.keys(menuItemsRef));
in this :
const sectionRefs = [
useRef(null),
useRef(null),
useRef(null),
];
What you are doing creates a ref that contains an array
useRef(Object.keys(menuItemsRef))
// { current: [...] }
What your hook seems to expect is an array that contains refs
const sectionRefs = [
useRef(null),
useRef(null),
useRef(null),
];
// [ { current: ... }, { current: ... }, { current: ... } ]
What you need to do is to keep the "properties" of a react ref (the fact that its content persists across renders) while giving it a structure that matches what your hook is expecting:
const refArray = useRef(Object.values(menuItemsRef).map(value => ({current: value})))
// { current: [ { current: ... }, { current: ... }, { current: ... } ] }
const activeSectionNavbar = useScrollSpy({
sectionElementRefs: refArray.current,
offsetPx: -80,
});
I would like to build it into my compose function so that record’s values go to the top level of the object, whilst the rest of the keys stay in tact:
{
record: {
seasons: [
1
],
colors: [
2
]
},
tag_ids: [
2091
]
}
The result I am after:
{
seasons: [
1
],
colors: [
2
],
tag_ids: [
2091
]
}
Any of the keys may or may not exist.
I have always scratched my head with the ramda way to do it in a compose function. Currently I am looking at toPairs and doing some pretty long winded transforms with no luck.
This may be simpler in plain JS rather than Ramda:
const data = { record: { seasons: [1], colors: [2] }, tag_ids: [2091] }
const flattenRecord = ({record = {}, ...rest}) => ({...record, ...rest})
flattenRecord(data) //=> {"colors": [2], "seasons": [1], "tag_ids": [2091]}
If you would still like to utilise Ramda for the solution, consider looking into R.mergeLeft (or R.mergeRight) and R.omit.
You can use R.chain with R.merge and R.prop to flatten a key's content by merging it with the original object, and then you can omit the original key.
const { pipe, chain, merge, prop, omit } = R
const fn = key => pipe(
chain(merge, prop(key)), // flatten the key's content
omit([key]) // remove the key
)
const data = { record: { seasons: [1], colors: [2] }, tag_ids: [2091] }
const result = fn('record')(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
You can use the spread operator.
const startingWithAllProps = {
record: {
seasons: [
1
],
colors: [
2
]
},
tag_ids: [
2091
]
}
const startingWithoutRecord = {
tag_ids: [
2091
]
}
const startingWithoutTagIds = {
record: {
seasons: [
1
],
colors: [
2
]
}
}
const moveRecordUpOneLevel = (startingObject) => {
const temp = {
...startingObject.record,
tag_ids: startingObject.tag_ids
}
return JSON.parse(JSON.stringify(temp)) // To remove any undefined props
}
const afterTransformWithAllProps = moveRecordUpOneLevel(startingWithAllProps)
const afterTransformWithoutRecord = moveRecordUpOneLevel(startingWithoutRecord)
const afterTransformWithoutTagIds = moveRecordUpOneLevel(startingWithoutTagIds)
console.log('afterTransformWithAllProps', afterTransformWithAllProps)
console.log('afterTransformWithoutRecord', afterTransformWithoutRecord)
console.log('afterTransformWithoutTagIds', afterTransformWithoutTagIds)
This might help too!
const lift = key => R.converge(R.mergeRight, [
R.dissoc(key),
R.prop(key),
]);
const liftRecord = lift('record');
// ====
const data = {
record: {
seasons: [
1
],
colors: [
2
]
},
tag_ids: [
2091
]
};
console.log(
liftRecord(data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js" integrity="sha256-buL0byPvI/XRDFscnSc/e0q+sLA65O9y+rbF+0O/4FE=" crossorigin="anonymous"></script>
I have a json array with different key values and need to add a ServerUrl to the beginning of all node values using a loop without writing multiple statements to do that by using javascript:
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
The expected result must be:
"Urls": [
{ "getCar": "http://192.168.1.1:3000/getAllCars" },
{ "getPerson": "http://192.168.1.1:3000/getAllPersons" },
{ "getBook": "http://192.168.1.1:3000/getAllBooks" }
],
Any advice would be appreciated.
You can use map to map your objects to new objects. Those objects have a single property, which you can get with Object.keys. The new object can get that same property name using the computed property name feature:
var obj = {
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
};
var urls = obj.Urls.map(o => Object.keys(o).map(k => ({ [k]: obj.ServerUrl + o[k] }))[0]);
console.log(urls);
const jsonVal = {
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
}
const result = jsonVal.Urls.map(val =>
Object.keys(val).reduce((resultObj, endpointKey) => {
resultObj[endpointKey] = `${jsonVal.ServerUrl}${val[endpointKey]}`;
return resultObj;
}, {})
);
Try (where your data are in d)
d.Urls.forEach( (x,i,a,k=Object.keys(x)[0]) => x[k] = d.ServerUrl + x[k]);
let d = {
"Urls": [
{ "getCar": "/GetAllGroupCustomers" },
{ "getPerson": "/getAllItems" },
{ "getBook": "/GetAllCustomers" }
],
"ServerUrl": "http://192.168.1.1:3000"
}
d.Urls.forEach( (x,i,a,k=Object.keys(x)[0]) => x[k] = d.ServerUrl + x[k]);
console.log(d);
A version that modifies your own object
var obj = {
"Urls": [
{ "getCar": "/getAllCars" },
{ "getPerson": "/getAllPersons" },
{ "getBook": "/getAllBooks" }
],
"ServerUrl": "http://192.168.1.1:3000"
};
obj.Urls.forEach(o => o[Object.keys(o)[0]] = `${obj.ServerUrl}${o[Object.keys(o)[0]]}`);
console.log(obj);