Angular .filter() not working on JSON response - json

From what I can tell, the .filter() method does not work on the response returned from .json() when there is only 1 single object in the return value. I am not sure how to go about dealing with this issue.
getFavorites() {
const userId = this.authService.getActiveUser().uid;
return this.http.get(this.databaseAddress + userId + '.json')
.map(
(response: Response) => {
return response.json();
})
.do(
(data) => {
if(data) {
this.favorites = data;
}else {
this.favorites = [];
}
})
}
this.favoritesService.getFavorites()
.subscribe(
(list: Recipe[]) => {
if(list) {
this.favoriteRecipes = list.filter(
item => item !== null
);
} else {
this.favoriteRecipes = [];
}
}
);
Error returned:
ERROR TypeError: list.filter is not a function

In case of no data returned from API, your response will be null/empty. And filter operation only works on Array type. Consider returning [] empty array from map operator.
getFavorites() {
const userId = this.authService.getActiveUser().uid;
return this.http.get(this.databaseAddress + userId + '.json')
.map(
(response: Response) => {
return response.json() || []; // return blank [] if data is null or empty
})
.do(
(data) => {
if(data) {
this.favorites = data;
}else {
this.favorites = [];
}
})
}

As you mentioned the issue here is not when response is null/empty, issue is when the response only has 1 object in it.
Just append whatever result you have to an empty array, and you are done...
getFavorites() {
const userId = this.authService.getActiveUser().uid;
return this.http.get(this.databaseAddress + userId + '.json')
.map(
(response: Response) => {
return response.json();
})
.do(
(data) => {
if(data) {
this.favorites = [].push(data);
}else {
this.favorites = [];
}
})

Related

strapi version 4 flatten complex response structure

Use this function to flatten the response returned from strapi on version 4. Helps you get rid of data and attributes properties
This will give you the same response structure as version 3 of strapi. This would help you migrate to version 4 from version 3 easily.
How to use it?
import the file.
const flattnedData = flattenObj({...data})
NOTE: The data here is the response returned from strapi version 4.
export const flattenObj = (data) => {
const isObject = (data) =>
Object.prototype.toString.call(data) === "[object Object]";
const isArray = (data) =>
Object.prototype.toString.call(data) === "[object Array]";
const flatten = (data) => {
if (!data.attributes) return data;
return {
id: data.id,
...data.attributes,
};
};
if (isArray(data)) {
return data.map((item) => flattenObj(item));
}
if (isObject(data)) {
if (isArray(data.data)) {
data = [...data.data];
} else if (isObject(data.data)) {
data = flatten({ ...data.data });
} else if (data.data === null) {
data = null;
} else {
data = flatten(data);
}
for (const key in data) {
data[key] = flattenObj(data[key]);
}
return data;
}
return data;
};
In my case I created a new middleware "flatten-response.js" in "middlewares" folder.
function flattenArray(obj) {
return obj.map(e => flatten(e));
}
function flattenData(obj) {
return flatten(obj.data);
}
function flattenAttrs(obj) {
let attrs = {};
for (var key in obj.attributes) {
attrs[key] = flatten(obj.attributes[key]);
}
return {
id: obj.id,
...attrs
};
}
function flatten(obj) {
if(Array.isArray(obj)) {
return flattenArray(obj);
}
if(obj && obj.data) {
return flattenData(obj);
}
if(obj && obj.attributes) {
return flattenAttrs(obj);
}
for (var k in obj) {
if(typeof obj[k] == "object") {
obj[k] = flatten(obj[k]);
}
}
return obj;
}
async function respond(ctx, next) {
await next();
if (!ctx.url.startsWith('/api')) {
return;
}
ctx.response.body = flatten(ctx.response.body.data)
}
module.exports = () => respond;
And I called it in "config/middlewares.js"
module.exports = [
/* ... Strapi middlewares */
'global::flatten-response' // <- your middleware,
'strapi::favicon',
'strapi::public',
];

get detail json in react

datajs = fetch(Constants.SPS_S_INVESTIGATOR_QB).then(async (response) => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.indexOf('application/json') !== -1) {
const jsn = await response.json();
return jsn['DBInfoScript'].replace('var ourDB=', '');
} else {
const text = await response.text();
}
});
useEffect(() => {
if (dataItem.length == 0) {
setdataItem(datajs);
}
}, [datajs]);
console.log(dataItem);
console.log(dataItem.airtravel);
I want get detail json but Output is undefined
output console.log(dataItem.airtravel) output = undefind
but console.log(dataItem) out put is full
Photo below the console output from console.log(dataItem)
I think you have a problem with the "dataItem" object. can you comment JSON output of "dataItem"?

How to extract key and value from json in fetch method in React Native?

I'm new in React Native. I would like to extract a value from json with fetch to do a simple test to begin. But I don't understand, how to select a particular key from Json. Always, I have undefined return. I tried to modify my code with this post but it doesn't work. I tried to parse before but he didn't want because it's already an object.
This is my code:
checkLogin = () => {
const { name } = this.state;
const { surname } = this.state;
fetch('https://ffn.extranat.fr/webffn/_recherche.php?go=ind&idrch=' + name + '%20' + surname, {
method: 'GET',
}).then((response) => response.json())
.then((responseJson) => {
if (responseJson.ind == 'Individu non trouv\u00e9 !') {
alert("Id incorrect")
}
else {
alert("Id correct");
}
alert(JSON.stringify(responseJson.ind))
}).catch((error) => {
console.error(error);
});
}
This is my JSON format:
[{"iuf":"1366701","ind":"LEBRUN L\u00e9o (2000) H FRA - CN BEAUPREAU","sex":"#1e90ff","clb":"CN BEAUPREAU"}]
I know my request work because when I run this code alert(JSON.stringify(responseJson)).It return the entire json. So I don't know, how to resolve the undefined return.
Regards
Your json is an array, you either need to loop through it if there is multiple items inside, or just use responseJson[0] to read it. So if you want to read your json, your code would look like this :
const checkLogin = () => {
const { name } = this.state;
const { surname } = this.state;
fetch(
"https://ffn.extranat.fr/webffn/_recherche.php?go=ind&idrch=" +
name +
"%20" +
surname,
{
method: "GET"
}
)
.then(response => response.json())
.then(responseJson => {
// Since you have only one object inside your json, you can read the first item with 'responseJson[0]'.
if (responseJson[0].ind == "Individu non trouv\u00e9 !") {
alert("Id incorrect");
} else {
alert("Id correct");
}
alert(JSON.stringify(responseJson[0].ind));
// If you have multiple elements inside your responseJson,
// then here is a loop example :
// responseJson.forEach(item => {
// console.log('item ind = ', item.ind);
// });
})
.catch(error => {
console.error(error);
});
};
Use async await.
const checkLogin = async () => {
const { name } = this.state;
const { surname } = this.state;
const request = await fetch(
"https://ffn.extranat.fr/webffn/_recherche.php?go=ind&idrch=" +
name +
"%20" +
surname)
const response = await request.json();
console.log('result from server', response)
}

How could I pass JSON object array result to my api URL? (In REACT)

I have to fetch 2 api from backend, and try to get the result from this two. but, at the moment, the JSON result I get from the first API is object Array in JSON. I need to pass the id from first API(using setState) to second API for path variables. But when I do in my way, it fail to retrieve the data. Consider the code below:
componentDidMount(){
// console.log(loginEmail)
fetch(`http://localhost:9000/api/item/list`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({data: res.data});
}
)
})
const id = this.state.data.id;
fetch(`http://localhost:9000/api/item/photo/view/${id}`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({res});}
)
})
}
The problem is that fetch returns a Promise so, at the line
const id = this.state.data.id;
You do not have data populated yet.
You have to concatenate the two requests in a way like the following:
componentDidMount() {
fetch(`http://localhost:9000/api/item/list`)
.then((resp) => {
// return the id
})
.then((id) => {
fetch(`http://localhost:9000/api/item/photo/view/${id}`)
.then((resp) => {
// do what you need with the result
})
})
}
Fetch is asynchronous, which means javascript will
fetch data on the first call with no waiting, and continue
to the second fetch call where the id is not defined or Null.
In order to fix that you can use promises as follow
My code example
import React from "react";
class Home extends React.Component {
constructor() {
super();
this.state = {
res: [],
}
}
// http://jsonplaceholder.typicode.com/users
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res);
}
)
})
})
}
async componentDidMount() {
let data = await this.fetchData("http://jsonplaceholder.typicode.com/users");
console.log("data :", data);
let id = data[0].id;
console.log("Id :", id);
let newData = await this.fetchData(`http://jsonplaceholder.typicode.com/users/${id}`);
this.setState({ res: newData });
}
render() {
return (
<div>
Call API
</div>
)
}
}
export default Home
Adapted on your code
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res.data);
}
)
})
})
}
async componentDidMount() {
// console.log(loginEmail)
let data = await this.fetchData("http://localhost:9000/api/item/list");
let id = data.id;
let newData = await this.fetchData(`http://localhost:9000/api/item/photo/view/${id}`);
this.setState({ res: newData });
}
You need to make sure that each id gets its relevant results.
async componentDidMount() {
await fetch(`http://localhost:9000/api/item/list`)
.then(async (resp) => {
let req_ = resp.map((item)=>{
return await fetch(`http://localhost:9000/api/item/photo/view/${item.id}`)
})
let result = Promise.all(req_)
console.log(result)
})
}

Query inside foreach Node.js Promis

i put query inside for each on promise. I am trying to query a mysql database twice, the second time, multiple times for each result from the first time but I am unable to work out how to wait for the result from the second query before continuing
i want the output like this :
{
"data":[
{
"name":"Title result",
"images":[
{
"id":1,
"place_id":705,
"path_image":"http://3.bp.blogspot.com/-iwF-ImFpzvk/T6fKhC6F7YI/AAAAAAAAARA/FyKpNcDsP8M/s1600/asd2e1.jpg"
},
{
"id":2,
"place_id":705,
"path_image":"https://asrt.bp.com/data/photo/2014/07/22/sddrfr2.jpg",
}
]
}
]
}
but i get only like this :
{
"data":[
{
"name":"Title result",
"images":[]
}
and this is my code:
return new Promise((resolve, reject) => {
const { connection, errorHandler } = deps;
let arrayData = [];
let imageData = [];
connection.query(
"SELECT * FROM places WHERE id = 705",
(error, rows, results) => {
rows.forEach((row) => {
connection.query(
"SELECT * FROM place_gallery WHERE place_id = 705",
(error, rows, results) => {
imageData = rows;
}
)
arrayData.push({ name: row.title, images: imageData })
});
if (error) {
errorHandler(error, "failed", reject);
return false;
}
resolve({ data: arrayData });
}
);
})
},
how to solve this?
try this, another way instated of creating dbcall function you can convert the query callback to promise using util.promisify()
const dbcall = (query) => {
return new Promise((resolve, reject) => {
connection.query(
query,
(error, rows, results) => {
if (error) return reject(error);
return resolve(rows);
});
});
};
const somefunc = async () => {
const {
connection,
errorHandler
} = deps;
let arrayData = [];
try {
const rows = await dbcall("SELECT * FROM places WHERE id = 705");
rows.forEach(async (row) => {
const imageData = await dbcall("SELECT * FROM place_gallery WHERE place_id = 705");
arrayData.push({
name: row.title,
images: imageData
});
});
} catch (error) {
console.log(error);
}
return arrayData;
}