How can I call another api in flat list? - reactjs

I have one API which has title, body, and user-id, and I want to print User Name with the help of another API. So how can I do it?
I have listed both APIs in below.
https://jsonplaceholder.typicode.com/posts
https://jsonplaceholder.typicode.com/users/1 // ${id}
getUser(id) {
let userData = fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then(response => response.json())
.then((responseJson) => {
return responseJson.name
})
.catch(error => console.log(error)) //to catch the errors if any
console.log(userData);
return userData;
};

what you can do is first get the posts and save it inside a variable .
then inside a map call other api to get the user data and append the user data in the variable
example
fetch('https://jsonplaceholder.typicode.com/posts',)
.then(response => {
let new_post = [];
let posts = response.json() ;
Promise.all(
posts.map(item => {
fetch('https://jsonplaceholder.typicode.com/users/'+item.userId)
.then(res =>{
item['user'] = res.json() ;
console.log(item)
new_post.push(item)
})
})
)
.then(() => {
this.setState({testing:new_post})
})
})
then in your flatlist display username by
<FlatList
data={this.state.testing}
renderItem={({item}) =>(
<View>
<Text>other</Text>
<Text>{item.user.email}</Text>
</View>
)
}
/>
OR if your are using axios to get data change code to
axios.get('https://jsonplaceholder.typicode.com/posts',)
.then(response => {})

Related

React JS fetch data from multiple API function

I was tasked to create a front-end for a poc. I am not a front end developer but I chose to use React JS.
There is only one page fetching data from multiple API endpoints. API endpoints return a simple json object.
I managed to get that to work however my code is ugly af and I want to create a function to handle all of that but I can't seem to get it right. Here's my code
export default class Dashboard extends React.Component {
constructor(props) {
super(props);
this.state = {
group1: [],
group2: [],
group3: [],
isLoaded: false,
}
}
componentDidMount() {
const group1_url = "http://localhost/api/1"
const group2_url = "http://localhost/api/2"
const group3_url = "http://localhost/api/3"
fetch(group1_url)
.then(res => res.json())
.then(json => {
this.setState({
group1: json,
})
});
fetch(group2_url)
.then(res => res.json())
.then(json => {
this.setState({
group2: json,
})
});
fetch(group3_url)
.then(res => res.json())
.then(json => {
this.setState({
group3: json,
})
});
}
I am trying to create a function like this:
function fetch_data(url, state) {
fetch(url)
.then(res => res.json())
.then(json => {
this.setState({
state: json,
})
});
}
var group1 = fetch_data(group1_url, group1);
So far no joy. How can I create a function to fetch data and set a state in js?
Alternatively how can I make my code look better? Or is there something else I should use/look into?
Pass a string as the second parameter, and use a computed property:
function fetch_data(url, state) {
fetch(url)
.then(res => res.json())
.then(json => {
this.setState({
[state]: json,
})
});
}
fetch_data(group1_url, 'group1');
I'd also highly recommend catching errors - possible unhandled rejections should be avoided whenever possible.
You might want to use Promise.all to wait for all groups to load:
const dataSources = {
group1: 'http://localhost/api/1',
group2: 'http://localhost/api/2',
group3: 'http://localhost/api/3',
};
Promise.all(
Object.entries(dataSources).map(([propertyName, url]) => (
fetch(url)
.then(res => res.json())
.then((result) => {
this.setState({
[propertyName]: result
})
})
))
)
.then(() => {
this.setState({ isLoaded: true })
})
.catch((error) => {
// handle errors
})
(also note that your json argument is not a JSON - JSON is only a format that exists with strings. Something that has been deserialized is just a plain object or array. Better to call it something less misleading, like result as I did)
You could try Promise.all
Promise.all takes an array of promises (it technically can be any iterable, but is usually an array) and returns a new promise.
const points = [
"http://localhost/api/1",
"http://localhost/api/2",
"http://localhost/api/3",
];
const responses = await Promise.all(points.map((point) => fetch(point)));
const data = await Promise.all(responses.map((response) => response.json()));
const [group1, group2, group3] = data;
this.setState({
group1,
group2,
group3,
});
Just remember to wrap this logic in an async function
You can do something like this.
function fetch_data(url, state) {
fetch(url)
.then(res => res.json())
.then(json => {
this.setState({
[state]: json,
})
});
}
var group1 = fetch_data(group1_url, 'group1');

How to push data into state array in react native

Suppose I have an array of ids that reflects my images [aaa, bbb, ccc]and I will be using that data to get my images.
I want to use these ids and get my images and store them in an array state which would be used to display my images in flatlist.
My code is as follows.
getIDs() {
fetch(config)
.then((response) => {
return response.json();
})
.then(async (data) => {
data.map(async id => {
await this.setImages(id.id)
} );}) }
async setImages(imageID) {
await fetch(config ) //where image Id is used
.then((response) => {
return response.json();
} })
.then(async (data) => {
await this.setState({ images: this.state.images.concat(data.content), isLoading: false }
})
The problem with this setState is that it changes the sequence of my images. I want to load my images in a specific sequence that I am getting from my database.
My Flatlist is as follows
<FlatList
data={[...this.state.images]}
numColumns={3}
renderItem={({ item, index }) => {
return (
<Image source={{ uri: 'data:image/png;base64,' + item }} />
);
}}
keyExtractor={(item, index) => index.toString()}
/>
Instead of setState there for each image, first make an array to contain images and push image there so that theres no change in order and while retrieving do that like you used to do
let imagesArray=[];
getIDs() {
fetch(config)
.then((response) => {
return response.json();
})
.then(async (data) => {
data.map(async id => {
await this.setImages(id.id)
} );
}
this.setState({imagesArray:imagesArray})
) }
async setImages(imageID) {
await fetch(config ) //where image Id is used
.then((response) => {
return response.json();
} })
.then(async (data) => {
// await this.setState({ images: this.state.images.concat(data.content), isLoading: false }
imagesArray.push (data.content)
}) :,
hope it helps

update state with data return undefined

I have one state called data that is empty object state={data:{}} I called RestAPI updated state USING set state when I console log it returned the data in the correct format but data that I need is this.state.data.title.rendered it says undefined but in console log it has data
Rest Api is like this:
{id:5,title:{rendered:"home is good"}}
fetch(`http://localhost/react-wordpress/wp-json/wp/v2/posts/${this.props.match.params.id}`)
.then((response) => response.json())
.then((responseJson) => {
const { title, fimg_url, content } = responseJson;
this.setState({ title, fimg_url, content });
this.setState({ data: responseJson })
})
.catch((error) => {
console.error(error);
});
In rendered method {this.state.data.title.rendered} return undefined while {this.state.title.rendered} return correct
Yes. Maybe it is undefined before fetching from backend.
So you need to validate if it is okay to render it like below:
const { data } = this.state;
return (
<div>
{ data && data.title && data.title.rendered
&& ( <h1>data.title.rendered</h1> )
}
<div>
);
try like this
fetch(`http://localhost/react-wordpress/wp-json/wp/v2/posts/${this.props.match.params.id}`)
.then((response) => response.json())
.then((responseJson) => {
const { title, fimg_url, content } = responseJson;
this.setState({ data: {title, fimg_url, content} });
})
.catch((error) => {
console.error(error);
});

How to pass query parameters to a url inside a lambda function (netlify environment)

When the user submit a search form I want to add the query parameter to the api url that is inside a lambda function.
I set up the netlify environment inside a react app and initialize a lambda function.Now I only get the response using hard-coded queries.
How can I pass parameters to the event.queryStringParameters?
exports.handler = function(event, context, callback) {
const API_PARAMS = qs.stringify(event.queryStringParameters);
const { API_TOKEN, API_URL } = process.env;
const URL = `${API_URL}search?part=snippet&maxResults=5&key=${API_TOKEN}&q=animals`;
// Let's log some stuff we already have.
console.log("Injecting token to", API_URL);
console.log("logging event.....", event);
console.log("Constructed URL is ...", URL);
console.log('params are...', API_PARAMS);
const pass = body => {
callback(null, {
statusCode: 200,
body: JSON.stringify(body)
});
};
const get = () => {
axios
.get(URL)
.then(response => {
console.log(response.data);
pass(response.data);
})
.catch(err => pass(err));
};
if (event.httpMethod == "GET") {
get();
}
};
App.js
componentDidMount() {
fetch('.netlify/functions/youtube')
.then(response => response.json())
.then(data => console.log(data));
}
this took me a minute to figure out but it's in the query string:
let thing = 123;
fetch(`/.netlify/functions/${filename}?item=${thing}`)
.then(response => response.json())
.then(json => console.log(json))
if it's a post, you will need to parse it from the query but a regular get call you can pull it out of the event.queryStringParameters

react native get response from then and assign to variable

I am trying to get thumbnail path and storing to a variable to be used, But I am getting undefined
getThumbnail(filePath){
let thumbnailURL = RNThumbnail.get(filePath)
.then((response) => response.path)
.then((responseData) => {
console.warn(responseData);
return responseData;
}).catch(error => console.warn(error));
alert(thumbnailURL);
//return thumbnailURL;
}
.then doesn't work like that, it won't return a value. You could do:
let thumbnailURL;
RNThumbnail.get(filePath)
.then((response) => response.path)
.then((responseData) => {
thumbnailURL = responseData;
alert(thumbnailURL);
}).catch(error => console.warn(error));
but you have to continue computation inside the second then call because the value is only going to be reliable there
You're better off using async/await, just refactor your code to this:
async function getThumbnail(filePath){
try {
let thumbnailURL = await RNThumbnail.get(filePath)
alert(thumbnailURL)
} catch(err) {
console.warn(err)
}
read more about async / await
For React app, most likely you will want to set the response as state:
state = {
thumbnailURL: ''
}
getThumbnail = (filePath) => {
RNThumbnail.get(filePath)
.then(response => response.path)
.then(responseData => {
this.setState({
thumbnailURL: responseData
})
})
.catch(error => console.warn(error))
}
render() {
return (
<img src={this.state.thumbnailURL} />
)
}
You will need arrow function on getThumbnail for lexical binding so that you can access this.setState().
Edit:
You can't actually make getThumbnail() return thumbnailURL value right away. getThumbnail() can however return the promise, and you resolve it at the place where you want access to thumbnailURL:
getThumbnail = filePath => {
return RNThumbnail.get(filePath)
.then(response => response.path)
.then(responseData => responseData)
.catch(error => console.warn(error))
}
IWannaAccessThumbnailURLHere = () => {
this.getThumbnail('....')
.then(thumbnailURL => {
// do things with thumbnailURL
})
}
Or, use setState, re-render then you can access this.state.thumbnailURL in the next render-cycle.

Resources