Data.map is not a function API request - javascript

I am trying to fetch API data but an error shows that data.map is not a function (in my case users.map). Please help me out.
I'm getting an error that map.data is undefined as a function? Looking at it I don't know what's not working .
import React, { useEffect, useState } from "react";
import "./bodypart.css";
const Bodypart = () => {
const [users, setUsers] = useState([]);
const getUsers = async () => {
const response = await fetch(
"https://www.flickr.com/services/rest/?method=flickr.photos.getRecent&api_key=XXXXXXXXXXXXXXXXXXXXX&format=json&nojsoncallback=1"
);
setUsers(await response.json());
};
useEffect(() => {
getUsers();
}, []);
return (
<div className="bodypart">
<div className="bodypart__image">
<div className="image">
{users.map((curElem) => {
return (
<img
src="https://www.thisislocallondon.co.uk/resources/images/12088462.jpg?display=1&htype=0&type=responsive-gallery"
classname="bodypart__image"
alt=""
/>
);
})}
</div>
</div>
</div>
);
};
export default Bodypart;
API DATA is given below. I am unable to solve the problem by myself.
{
"photos": {
"page": 1,
"pages": 10,
"perpage": 100,
"total": 1000,
"photo": [
{
"id": "51398681312",
"owner": "193303965#N08",
"secret": "594df2ff71",
"server": "65535",
"farm": 66,
"title": "",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "51398681362",
"owner": "193209554#N03",
"secret": "2de06284c5",
"server": "65535",
"farm": 66,
"title": "SPIDERMAN NO WAY HOME RETOUCHES",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
{
"id": "51398682272",
"owner": "193683913#N05",
"secret": "d8258fa802",
"server": "65535",
"farm": 66,
"title": "Türkiyədə FACİƏ: Sosial şəbəkə üçün video çəkən qız yüksəklikdən yerə çırpıldı - ANBAAN VİDEO",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},
]
}
EDIT: Hello Friends , I got the answer instead of
{users.map((curElem) => {
we will have to write
{users.photos.photo.map((curElem) => {
EDIT 2
What should I write inside my console statement to return id of photo
{
"photos": {
"page": 1,
"pages": 10,
"perpage": 100,
"total": 1000,
"photo": [
{
"id": "51400489782",
"owner": "144450638#N02",
"secret": "2e68b6bb36",
"server": "65535",
"farm": 66,
"title": "riki-shaham-wong-ping",
"ispublic": 1,
"isfriend": 0,
"isfamily": 0
},

Clearly your API call is returning undefined or something of that nature, which sets the users to undefined. Then when you use in later, you can't call map on undefined, which is the error you are getting.
You must first verify why that's happening and put some defaults so you don't run into run time exceptions.
setUsers((await response.json()) ?? []);

Check your fetch part inside getUsers. I copied the API address and got this error.
{"stat":"fail","code":100,"message":"Invalid API Key (Key has invalid format)"}
You can update your funtion as follow.
const response = await fetch(
...url
);
const data = response.json()
if(Array.isArray(data))
setUsers(data);

Try putting a console.log(users) somewhere in that component to see what fetch is returning from flickr. It may be an object that you need to extract an array property from.
Then check the browser developer tools console. You should see two console outputs before the type error; an empty array from the first rendering [] and the response from the fetch call during the second rendering.
const [users, setUsers] = useState([]);
console.log('Users: ', users);

Related

Why can't access my new state value from another function in react.js hook?

I set my marinaList new value. I can access marinaList state in GetMarinaList function. But when I try access marinaList state in GetCounterConnectionDevices function I get inital value of marinaList. Why I can't access my current value of my state in another function ?
import React, { useState, useCallback, useEffect } from "react";
function CounterConnectionDeviceDefinition(props) {
const [marinaList, setMarinaList] = useState([]);
useEffect(() => {
GetMarinaList();
}, [])
const GetMarinaList = () => {
const RETRIEVED_MARINAS = [
{
"Oid": 3348000013080006,
"Status": 1,
"LastUpdated": 1615185446387,
"OperationRefNo": 1459738,
"MarinaCode": 1,
"MarinaName": "MERSİN MARİNA",
"MarinaLocation": "MERSİN",
"IsActive": true
},
]
setMarinaList(RETRIEVED_MARINAS)
console.log(" RETRIEVED_MARINAS", RETRIEVED_MARINAS); //I get retrieved marina data
GetCounterConnectionDevices(-1);
}
const GetCounterConnectionDevices = () => {
const RETRIEVED_COUNTER_CONNECTION_DEVICES = [
{
"Oid": 3348000013898110,
"Status": 1,
"LastUpdated": 1618484345355,
"OperationRefNo": 1498555,
"PedestalControlCenterOid": 3348000013898011,
"CounterParameterType": {
"Oid": 0,
"Status": 0,
"LastUpdated": 0,
"OperationRefNo": 0,
"ParameterTypeOid": 0,
"ParameterName": null,
"ParameterCode": "001",
"ParameterExplanation": null
},
"CounterConnectionDeviceModelName": "LUNA_BC62_ANTALYA",
"CounterConnectionDeviceId": "6-0-64-228-24-0-0-0",
"CounterConnectionDevicePassword": null,
"CounterConnectionDeviceIpAddress": null,
"CounterConnectionDevicePortNumber": null,
"IsActive": true
},
]
console.log("🚀 => status.then => RETRIEVED_COUNTER_CONNECTION_DEVICES", RETRIEVED_COUNTER_CONNECTION_DEVICES, marinaList); // I get Retrieved Counter Array and [].
}
return (
<div>
</div>
)
}
export default CounterConnectionDeviceDefinition
Because react updates states async.
This means that right after calling setMarinaList(RETRIEVED_MARINAS) the state hasn't changed yet. The list is still empty.
That's why you have useEffect.
If you need to run a function when the state changes that's your friend. You can change your code to something like this
useEffect(() => {
const RETRIEVED_COUNTER_CONNECTION_DEVICES = [
{
"Oid": 3348000013898110,
"Status": 1,
"LastUpdated": 1618484345355,
"OperationRefNo": 1498555,
"PedestalControlCenterOid": 3348000013898011,
"CounterParameterType": {
"Oid": 0,
"Status": 0,
"LastUpdated": 0,
"OperationRefNo": 0,
"ParameterTypeOid": 0,
"ParameterName": null,
"ParameterCode": "001",
"ParameterExplanation": null
},
"CounterConnectionDeviceModelName": "LUNA_BC62_ANTALYA",
"CounterConnectionDeviceId": "6-0-64-228-24-0-0-0",
"CounterConnectionDevicePassword": null,
"CounterConnectionDeviceIpAddress": null,
"CounterConnectionDevicePortNumber": null,
"IsActive": true
},
]
console.log("🚀 => status.then => RETRIEVED_COUNTER_CONNECTION_DEVICES", RETRIEVED_COUNTER_CONNECTION_DEVICES, marinaList); // I get Retrieved Counter Array and [].
}, [marinaList])
And you can remove GetCounterConnectionDevices(-1); call now.
Note: your useEffect will also be called once, when the components mounts, so most likely you need to to a check for an empty array.
Because everytime you are using your hook in different component youre creating new instance with separated state. If you want to share your state in this hook across multiple components, use ContextAPI in custom hook

Why is my component not rendering a prop value?

I have a simple component tree:
RecipeFeed which renders Recipe
In my RecipeFeed component I map an an array of recipe objects to render a Recipe component for each recipe object in the array
const renderRecipes = () => {
if (recipes) {
return (
<div>
{recipes.map(recipe =>
<Recipe
key={recipe.id}
recipe={recipe}
ingredients={recipe.ingredients}/>
)}
</div>
)
} else {
return (
<div>
....loading
</div>
)
}
}
My Recipe component is similar:
const renderIngredients = () => {
if (props.ingredients) {
props.ingredients.map(ingredient => {
console.log(ingredient.name)
<div>{ingredient.name}</div>
})
}
}
return (
<div>
<div>{props.recipe.name}</div>
{renderIngredients()}
</div>
)
}
My recipe.name is OK, and renders to the DOM. However, although my ingredients are defined in the console.log in Recipe.jsx, Nothing is rendered to the screen.
I believe it must have something to do with the shape of the data and the way I am trying to access the value, but I am confused why it appears to be okay when inspecting the console log - right value type of string, no errors, etc.
The json data looks like this
"data": [
{
"id": 2,
"name": "pizza",
"ingredients": [
{
"id": 5,
"name": "dough",
"food_group": "grain",
"created_at": "2022-03-08T04:39:41.334Z",
"updated_at": "2022-03-08T04:39:41.334Z"
},
{
"id": 6,
"name": "sauce",
"food_group": "vegetable",
"created_at": "2022-03-08T04:40:11.684Z",
"updated_at": "2022-03-08T04:40:11.684Z"
},
{
"id": 7,
"name": "cheese",
"food_group": "dairy",
"created_at": "2022-03-08T04:40:33.032Z",
"updated_at": "2022-03-08T04:40:33.032Z"
}
],
"recipe_ingredients": [
{
"id": 3,
"recipe_id": 2,
"ingredient_id": 5,
"quantity": null,
"measurement_unit": null,
"created_at": "2022-03-08T04:41:06.482Z",
"updated_at": "2022-03-08T04:41:06.482Z"
},
{
"id": 4,
"recipe_id": 2,
"ingredient_id": 6,
"quantity": null,
"measurement_unit": null,
"created_at": "2022-03-08T04:41:06.484Z",
"updated_at": "2022-03-08T04:41:06.484Z"
},
{
"id": 5,
"recipe_id": 2,
"ingredient_id": 7,
"quantity": null,
"measurement_unit": null,
"created_at": "2022-03-08T04:41:06.485Z",
"updated_at": "2022-03-08T04:41:06.485Z"
}
]
}
You've got numerous mistakes here.
First: the second return statement is not inside a function. It's not part of the renderIngredients function -- which it can't be anyway, since then it would call itself. (Yes, recursion is legit in javascript, but this case would be perfectly circular and thus break.)
(On second glance, this is maybe because you forgot to include the beginning of the Recipe component, but we're not mind readers here.)
Second: your renderIngredients function won't accomplish anything, because: (1) it does not return anything, and (2) the map inside it also doesn't return anything. This is the direct answer to your question, "Why is my component not rendering a prop value?": it's because you haven't chosen to return anything, either with the return keyword, or by using the short arrow form: () => returnValue.
Third: the signature of your Recipe component is bad:
<Recipe
key={recipe.id}
recipe={recipe}
ingredients={recipe.ingredients}
/>
Why are you passing both the recipe and the ingredients separately? The component can access the ingredients through the recipe. You've set it up so that the same data has to be fed into it twice.
Fourth: the names of component functions must start with a capital letter so that the React framework recognizes them as custom components instead of native HTML components. And don't name your component "renderRecipes", name it "RecipeList".

I'm getting no response of GET request with Axios on my Node.js API

I'm trying to develop an API with Node.js using Axios, to get all deals from Pipedrive. I already have the Pipedrive URL to make the requests, which is similar to this one: https://mydomain.pipedrive.com/api/v1/deals?api_token=${API_TOKEN} and I have also the API token for authentication.
I've tested this GET request on Postman, with the URL, and it works just fine - I get the JSON response with all the deals correctly - but when I'm trying to make the request using the Axios I get no response. I've tried to do it in so many ways, but none of them really worked.
I've created an async function called "getAllDealsPipedrive" using a Try-Catch method, and put the axios.get(url) there to make the request. I'm calling the function in my route /deals using the Router function from express. When I make a GET request on http://localhost:8080/v1/deals on the Postman it returns me a bad request (400).
I have no experience with axios. I would really appreciate if someone could help me to get these requests work.
My controller looks like:
require('dotenv')
const Deal = require('./models/Deal')
const axios = require('axios')
const API_TOKEN = process.env.API_TOKEN
const API_URL = process.env.API_URL
class dealController {
async getAllDealsPipedrive(req, res){
try {
const response = await axios.get(`${API_URL}api_token=${API_TOKEN}`,
{params: {data: data.body}}
)
return res.status(200).json(response)
}
catch (error) {
return res.status(400).json({"message":error})
}
}
}
module.exports = new Controller()
My routes file looks like:
const express = require('express')
const router = express.Router()
const controller = require('../controllers/dealController')
router.get('/deals', controller.getAllDealsPipedrive)
module.exports = router
An example of the expected JSON response:
{
"success": true,
"data": [
{
"id": 1,
"creator_user_id": {
"id": 13540546,
"name": "Foo Bar",
"email": "foo.bar#test.com",
"has_pic": 0,
"pic_hash": null,
"active_flag": true,
"value": 13540546
},
"user_id": {
"id": 13540546,
"name": "Foo Bar",
"email": "foo.bar#test.com",
"has_pic": 0,
"pic_hash": null,
"active_flag": true,
"value": 13540546
},
"person_id": {
"active_flag": true,
"name": "Foo",
"email": [
{
"value": "",
"primary": true
}
],
"phone": [
{
"value": "",
"primary": true
}
],
"owner_id": 13540546,
"value": 1
},
"org_id": null,
"stage_id": 1,
"title": "deal test",
"value": 35,
"currency": "BRL",
"add_time": "2021-11-11 02:36:37",
"update_time": "2021-11-11 02:38:47",
"stage_change_time": null,
"active": false,
"deleted": false,
"status": "won",
"probability": null,
"next_activity_date": null,
"next_activity_time": null,
"next_activity_id": null,
"last_activity_id": null,
"last_activity_date": null,
"lost_reason": null,
"visible_to": "3",
"close_time": "2021-11-11 02:38:47",
"pipeline_id": 1,
"won_time": "2021-11-11 02:38:47",
"first_won_time": "2021-11-11 02:38:47",
"lost_time": null,
"products_count": 0,
"files_count": 0,
"notes_count": 0,
"followers_count": 1,
"email_messages_count": 0,
"activities_count": 0,
"done_activities_count": 0,
"undone_activities_count": 0,
"participants_count": 1,
"expected_close_date": "2021-11-25",
"last_incoming_mail_time": null,
"last_outgoing_mail_time": null,
"label": null,
"renewal_type": "one_time",
"stage_order_nr": 0,
"person_name": "Foo",
"org_name": null,
"next_activity_subject": null,
"next_activity_type": null,
"next_activity_duration": null,
"next_activity_note": null,
"group_id": null,
"group_name": null,
"formatted_value": "R$ 35",
"weighted_value": 35,
"formatted_weighted_value": "R$ 35",
"weighted_value_currency": "BRL",
"rotten_time": null,
"owner_name": "Foo Bar",
"cc_email": "test+deal1#pipedrivemail.com",
"org_hidden": false,
"person_hidden": false
}
I've solved my problem, after all using this code:
async getAllDealsPipedrive(_, res){
try {
const response = await axios.get(`${PIPE_URL}?api_token=${PIPE_TOKEN}`)
return res.json(response.data)
}
catch (err) {
console.log(err)
}
}
you can check "network" tab in debug bar(ctrl + shift + i or F12), to see wha is happening in your request, but looking you code, the axios lib havea config to use query params in their functions, in get looks like:
const response = await axios.get(API_URL, {params: {api_token: API_TOKEN}})`;
But see too, that you trying so send a body in GET request, this not usual, even that doesn't work, axios does not have to support to send get reques with body, to the best solution is:
const response = await axios.get(API_URL, {params: {api_token: API_TOKEN}, body: data.body})`;
In this way, token and body will be sent in query in URL, other way is change HTTP method to POST and put the body var in second argument, like this:
const response = await axios.post(API_URL, data.body,{params: {api_token: API_TOKEN}})`;
But if you really need to use GET with body, I recommend three approaches, first is overwrite some axios methods(the hardway) to use GET with body, if second is use interceptor of axios, and manually put the body in GET request, and the thrird is use other lib that have support

Where am i going wrong with this array filter? Reactjs

I am mapping over some data that I am getting from a api however when i try to add the filter function i get 'currencyData.includes is not a function'
I have also tried just hard coding the array but it also still doesnt work?
I have a loading state for when i fetch data from the api which holds code from being run but i have removed it from this example as its not getting data from the api below.
The simplified version is here...
ARRAY
var items = [
{
"id": 1,
"productName": "shoes",
"productIdentifier": "CL001",
"productDescription": "adidas kicks boir",
"productPrice": 2000,
"productStock": 200,
"created_at": "2020-51-28",
"updated_at": null
},
{
"id": 2,
"productName": "burger",
"productIdentifier": "FD001",
"productDescription": "charsiu berger",
"productPrice": 2000,
"productStock": 200,
"created_at": "2020-51-28",
"updated_at": null
}
]
return(
{items.filter(currencyInfo => currencyInfo.includes("FD001")).map((value, index) => {
console.log(value)
return(
<h1 key={index}>{value}</h1>
)
})}
)
currencyInfo is not an array, you can not call includes on it
Here is my suggestion:
return(
{items.filter(currencyInfo => currencyInfo.productIdentifier === "FD001").map((value, index) => {
console.log(value)
return(
<h1 key={index}>{value}</h1>
)
})}
)
More about includes()
The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate. Check this Doc
But in items.filter(currencyInfo => currencyInfo.includes("FD001")), type of currencyInfo isn't array but object.
So you should use currencyInfo.productIdentifier.includes()

Accessing nested JSON data with React Hooks & Props

I'm trying to access data further down into my JSON file. I am able to easily access data in the first two data sets in rows and area:
data.json
"rows": [
{
"uid":"001",
"type": "Lorem ipsum",
"area": [
{
"name": "London",
"number": "12345",
"wait": {
"start": {
"start_time": 1585129140,
"delay": 300
},
"end": {
"end_time": 1585130100,
"delay": 300
}
},
"in": 1585129140,
"out": 1585130100,
},
However when I try to access the data under wait which includes this block:
"wait": {
"start": {
"start_time": 1585129140,
"delay": 300
},
"end": {
"end_time": 1585130100,
"delay": 300
}
},
No data is getting returned on screen from my jsx file, but it is available in the console log
TimeTracker.jsx
const TimeTracker = (props) => {
const trainTime = useState(props.data);
console.log(props.data);
return (
<>
<div className={style.timeLabel}>
<div className={style.startTime}>{trainTime.start_time}</div>
<div className={style.endTime}></div>
</div>
</>
)
};
export default TimeTracker;
console.log
wait:
start:
start_time: 1585129140
delay: 300
__proto__: Object
end:
end_time: 1585130100
delay: 300
__proto__: Object
__proto__: Object
I've used the same pattern for passing props in other components and it works fine on the first two levels so I don't understand why it's not working. How do I get data from further in this JSON?
useState returns a tuple with the object and a function to set the value on the object. You probably need to change your component to something like this:
const TimeTracker = (props) => {
const [trainTime, setTrainTime] = useState(props.data);
console.log(props.data);
return (
<>
<div className={style.timeLabel}>
<div className={style.startTime}>{trainTime.start_time}</div>
<div className={style.endTime}></div>
</div>
</>
)
};
export default TimeTracker;
A nested property can not be accessed by one level of a.b so instead of
<div className={style.startTime}>{trainTime.start_time}</div>
it should be
<div className={style.startTime}>{trainTime.wait.start.start_time}</div>

Categories

Resources