Getting Error: Cannot read properties of undefined (reading 'map') chartjs - reactjs

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()
}, []);

Related

Return in tabular format in reactjs

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

How useStoreState is referring values in react?

I am pretty new to react and easy-peasy, I am stuck with one implementation with useStoreState.
I just want to understand how the useStoreState and useStoreAction work in the below code and how state.AdminCompanyInfo and action.AdminCompanyInfo are getting resolved.
I don't find any simple-to-understand example. Please help.
here is the code
const AdminCompanyInfo = () => {
var userType = isDesignerUser ? 1 : 2;
const [hideInactiveUser, setHideInactiveUser] = useState();
const {
roles: { data: roles },
companyUsers: state,
inactiveUserSetting: { response: orgSetting },
} = useStoreState(state => state.AdminCompanyInfo);
const {
companyUsers: { fetch },
companyUsers: actions,
roles: { fetch: fetchRoles },
inactiveUserSetting: { update: updateOrgSetting },
} = useStoreActions(actions => actions.AdminCompanyInfo);
useEffect(() => {
fetchRoles(userType);
fetch();
}, []);
}

In react-table with React Hooks, how to make a get request inside Cell?

I have been working with React-table for a couple of days now, my first time using it, and I have ran into some issues I can't quite seem to resolve. I am trying to build a table where I can show data from two API get requests at the same time, and since I don't know if there is a way to connect the two requests data into one object, and I wouldn't know how to do it, I was trying to access some of the data with get requests inside the react-table Column Cell itself.
My case being: I have two objects, Contacts and Institutions, contacts have in their data the institution ID as parameter, and I need to show in the table both the contact information and some information of the institution that is linked to it, getting it from the institution ID that is present in the contact data.
Here is one example of contact:
{
"contact_id": "34378a25-fe8c-4c64-bd35-59eab3f30863",
"institution_id": "ae1d0fe8-cce1-40ef-87d7-729dfbe9716d",
"name": "Contato 2",
"role": "Cargo 1",
"phone_numbers": [],
"emails": [],
"createdAt": "2021-03-09T20:40:26.6863764Z",
"updatedAt": "2021-03-09T20:40:26.686376448Z",
"deleted": false
}
And here is the institution data:
{
"institution_id": "ae1d0fe8-cce1-40ef-87d7-729dfbe9716d",
"name": "Matheus Salles Blanco",
"socialReason": "teste",
"cnpj": "99999999999999",
"abbreviation": "Matheus",
"website": "teste.com",
}
This is the code that is being implemented, reduced to only the parts that matter and that is working, but only showing the info that is being fetched from the contact object:
const Contacts = ({ match }) => {
const [data, setData] = useState([]);
const [institution, setInstitution] = useState();
const dataRecoil = useRecoilValue(contactData);
const handleContact = useCallback(async () => {
const response = dataRecoil.data;
if (response) {
setData(response.filter((contact) => !contact.deleted));
}
}, [setData, dataRecoil]);
useEffect(() => {
handleContact();
}, [handleContact]);
const columns = useMemo(
() => [
{
Header: 'Nome',
accessor: 'name',
},
{
Header: 'Sigla',
accessor: 'abbreviation',
},
{
Header: 'Nome Fantasia',
accessor: 'institution_id',
},
],
[editToggle, handleDelete],
);
return (
<>
<Table columns={columns} data={data} />
</>
);
};
And a print of it:
And here is what I have been trying to do:
const Contacts = ({ match }) => {
const [data, setData] = useState([]);
const [institution, setInstitution] = useState();
const dataRecoil = useRecoilValue(contactData);
const handleContact = useCallback(async () => {
const response = dataRecoil.data;
if (response) {
setData(response.filter((contact) => !contact.deleted));
}
}, [setData, dataRecoil]);
useEffect(() => {
handleContact();
}, [handleContact]);
const columns = useMemo(
() => [
{
Header: 'Nome',
accessor: 'name',
},
{
Header: 'Sigla',
accessor: 'abbreviation',
},
{
Header: 'Nome Fantasia',
accessor: 'institution_id',
Cell: async ({ cell }) => {
const response = await getInstitutionById(cell.row.values.institution_id);
const result = [response.data];
const inst = result.map((inst) => {return inst.name});
const institution_name = inst[0];
console.log(institution_name);
return institution_name;
},
},
],
[editToggle, handleDelete],
);
return (
<>
<Table columns={columns} data={data} />
</>
);
};
Which works at the level of fetching the right data, but does not render the page and shows errors:
The error
The right data being shown in the console.log
The expected output would be to show those names on the console.log on place of that long ID of the first picture.
So, is it possible to do what I am trying to do? And if so, what might am I be doing wrong?
I believe the issue is that you are providing an async function for your cell, which will return a Promise, not the institution name as you are expecting.
A potential solution is to instead create a custom Cell component that uses state to store the institution name. I have provided an example below, which was guided by this example, however I have not tested the code at all, so use it as more of a guide.
const MyCell = ({ cell }) => {
const [institutionName, setInstitutionName] = useState('fetching...')
useEffect(() => {
const getInstitutionName = async (id) => {
const response = await getInstitutionById(id);
const result = [response.data];
const inst = result.map((inst) => {return inst.name});
const institution_name = inst[0];
console.log(institution_name);
setInstitutionName(institution_name)
}
getInstitutionName(cell.row.values.institution_id)
}
return institutionName
}
const Contacts = ({ match }) => {
const [data, setData] = useState([]);
const [institution, setInstitution] = useState();
const dataRecoil = useRecoilValue(contactData);
const handleContact = useCallback(async () => {
const response = dataRecoil.data;
if (response) {
setData(response.filter((contact) => !contact.deleted));
}
}, [setData, dataRecoil]);
useEffect(() => {
handleContact();
}, [handleContact]);
const columns = useMemo(
() => [
{
Header: 'Nome',
accessor: 'name',
},
{
Header: 'Sigla',
accessor: 'abbreviation',
},
{
Header: 'Nome Fantasia',
accessor: 'institution_id',
Cell: MyCell
},
],
[editToggle, handleDelete],
);
return (
<>
<Table columns={columns} data={data} />
</>
);
};

Connecting 2 different arrays from the same external link - React hooks fetch

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);
};
] 

Initialize an array in a React Native useState

I'm working on a react native application.
I get the result of an SQL query like this:
const [ food, setFood ] = useState([]);
const load_food = async () => {
db.listProduct().then(row => setFood(row))
};
useFocusEffect( () => { load_food(food) }, [ food ] );
If I make a log like this:
console.log(food[i].PRODUCTNAME)
I get the name of my ingredient:
"Orange Juice"
Later I want to create a list from the variable food
const [listData, setListData] = useState(
Array(10)
.fill('')
.map((_, i) => ({ key: `${i}`, text: `Product name: ${food[i].PRODUCTNAME}`}))
);
But I have the following error:
undefined is not an object (evaluating 'food[i].PRODUCTNAME')
I imagine it's a synchronization issue. But I don't know how to solve it
You're mainly correct, it could be a sync problem, and you can use some techniques to avoid it, useEffect is one of them
const [listData, setListData] = useState([]);
useEffect(()=> {
setListData(
Array(10)
.fill('')
.map((_, i) => ({ key: `${i}`, text: `Product name: ${food[i].PRODUCTNAME}`}))
)
}, [food]);
This will only set listData state when food is updated, but also you will have to check food has at least 10 items or you will get undefined again

Resources