Using fetch to render json data in react app - json

I am trying to render some JSON about a person's location from an api in my react app.
I am using isomorphic-fetch to access the data from the API I can add the base test in and it correctly logs the data using below.
require('isomorphic-fetch');
require('es6-promise').polyfill();
var url = 'http://localhost:3000/api/data'
fetch(url)
.then(function(response) {
if (response.status >= 400) {
throw new Error("Bad response from server");
}
return response.json();
})
.then(function(data) {
console.log(data);
});
What i'm trying to work out is how I can take this response and render it in my component which currently looks like this (in this example code below data is coming from local json file so i need to merge them together).
I've attempted to set up componentDidMount but could get my head around the syntax so it kept breaking, I also checked out redux actions but that exploded my brain.
const personLoc = Object.keys(data.person.loc).map((content, idx) => {
const items = data.person.loc[content].map((item, i) => (
<p key={i}>{item.text}</p>
))
return <div key={idx}>{items}</div>
})
export default function PersonLocation() {
return (
<div className="bio__location">
{personLoc}
</div>
)
}

componentDidMount should setState:
componentDidMount() {
var that = this;
var url = 'http://localhost:3000/api/data'
fetch(url)
.then(function(response) {
if (response.status >= 400) {
throw new Error("Bad response from server");
}
return response.json();
})
.then(function(data) {
that.setState({ person: data.person });
});
}
The render component should map the state:
const personLoc = Object.keys(this.state.person.loc).map((content, idx) => {
const items = this.state.person.loc[content].map((item, i) => (
<p key={i}>{item.text}</p>
))
return <div key={idx}>{items}</div>
})

Related

Why am i only seeing "id" in my react app when the fetch get all the data from Strapi?

i am trying Strapi for the first time, and i cant put my raw data into my divs.
On Strapi everything is published, and for the public the get and getOne is checked.
This way i can only see the "id" nothing else.
Any guess?
here is my result from fetch:
Here is the code that i got from the tutorial page:
import { useEffect, useState } from 'react';
import "./App.css"
// Parses the JSON returned by a network request
const parseJSON = (resp) => (resp.json ? resp.json() : resp);
// Checks if a network request came back fine, and throws an error if not
const checkStatus = (resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp;
}
return parseJSON(resp).then(resp => {
throw resp;
});
};
const App = () => {
const [error, setError] = useState(null);
const [restaurants, setRestaurants] = useState([]);
useEffect(() => {
fetch('http://localhost:1337/api/restaurants', { headers:{ 'Content-Type': 'application/json' },
method: 'GET' })
.then(checkStatus)
.then(parseJSON)
.then(({ data }) => setRestaurants(data))
.catch((error) => setError(error))
}, [])
if (error) {
// Print errors if any
return <div>An error occured: {error.message}</div>;
}
return (
<div>
<div>
{restaurants.map(({ id, name, description }) => (
<div className="black" key={id}>
{name}
{description}
{id}
</div>
))}
</div>
</div>
);
};
export default App;
I figured it out forom Google.
The map section needs to be changed to this:
{restaurants && restaurants.map((restaurant) => (
<div className="black" key={restaurant.id}>
{restaurant.attributes.name}
{restaurant.attributes.description}
{restaurant.id}
{restaurant.attributes.publishedAt}
</div>
))}

Cannot map results from API

I'm trying to dynamically generate routes in my next.js application. I have an api called getUsers that returns something like this:
{"users":[{"_id":"639a87ae8a128118cecae85b","username":"STCollier","image":"https://storage.googleapis.com/replit/images/1641322468533_db666b7453a6efdb886f0625aa9ea987.jpeg","admin":false,"likedPosts":["639e34c5991ecaea52ace9e4","639e34c7991ecaea52ace9e7","639e34c7991ecaea52ace9ea","639e39a216a642f686a28036","639e39a216a642f686a28037","639e3b3d8cdebd89d9691f97","639e3b3d8cdebd89d9691f98","639e3b3e8cdebd89d9691f9d","639e3b5a8cdebd89d9691fa0","639e3b5c8cdebd89d9691fa3","639e3b5c8cdebd89d9691fa6"],"dislikedPosts":[""]},{"_id":"639a88abc4274fba4e775cbe","username":"IcemasterEric","image":"https://storage.googleapis.com/replit/images/1646785533195_169db2a072ad275cfd18a9c2a9cd78a1.jpeg","admin":false,"likedPosts":[],"dislikedPosts":[]}
So I know the API works succesfully, but when trying to get these api results and generate a page for each username, I get an error stating:
TypeError: users.map is not a function
Here's my code for generating the routes:
//pages/user/[username].js
const Get = async (url) => {
return await fetch(url).then(r => r.json());
}
export async function getStaticPaths() {
const users = Get('/api/getUsers')
return {
paths: users.map(u => {
const username = u.users.username
return {
params: {
username
}
}
}),
fallback: false
}
}
What is wrong with my getStaticPaths() code? I know that the API is working, so why can't I map the results?
And if anyone needs the code for api/getUsers, here is that:
import clientPromise from "../../lib/mongodb";
import nc from "next-connect";
const app = nc()
app.get(async function getUsers(req, res) {
const client = await clientPromise;
const db = client.db("the-quotes-place");
let users = []
try {
const dbUsers = await db
.collection("users")
.find({})
.toArray();
users = dbUsers
return res.json({
users: JSON.parse(JSON.stringify(users)),
success: true
})
} catch(e) {
return res.json({
message: new Error(e).message,
success: false,
});
}
})
export default app
Thanks for any help!!
Modify Get method to return an async value instead of Promise.
As Get is an async method, you need the await in getStaticPaths method.
const Get = async (url) => {
let response = await fetch(url);
return await response.json();
}
export async function getStaticPaths() {
const users = await Get('/api/getUsers');
...
}

How to print json api data in reactjs

I'm fetching json api details through GET request and trying to print it. Getting an error:
Error in the console is Uncaught ReferenceError: allUsers is not defined
const Dashboard = ({status, juser}) => {
const [allUsers, setAllUsers] = React.useState([]);
const id = juser.actable_id;
console.log(id); //getting id here as 1
const getAllusers = () => {
axios
.get(`http://localhost:3001/user/${id}`, { withCredentials: true })
.then((response) => {
console.log(response.data);
setAllUsers(response.data);
})
.catch((error) => {
console.log(" error", error);
});
};
React.useEffect(() => {
getAllusers();
}, []);
{allUsers.map((job_seeker, index) => {
return (
<div>
<p>{job_seeker.name}</p>
</div>
);
})}
}
export default Dashboard;
I'm new to react. Any help is appreciatable.
const [state, setState] = React.useState([]);
the state is where your data is located and setState is function to reset the state from anywhere,
so on your code,
const [jobseekers, allUsers] = React.useState([]); // change string to array
jobseekers is the variable where your data is located and allUsers is the function to store data into state.
set data to state using allUsers function,
const getAllusers = () => {
axios
.get(`http://localhost:3001/user/${id}`, { withCredentials: true })
.then((response) => {
allUsers(response.data);
})
.catch((error) => {
console.log(" error", error);
});
};
and map from jobseekers
{jobseekers.map((job_seeker, index) => {
return (
<div>
<p>{job_seeker.name}</p>
</div>
);
})}
Also I would suggest to rename your state and setState as,
const [allUsers, setAllUsers] = React.useState([]);
You didn't pass the value of response to allUsers, instead, you just created a new variable. So change
const allUsers = response.data;
to:
allUsers(response.data)
Besides, you can also improve the way that you have used useState. You have initialized it as an empty string while you'll probably store an array from response in jobseekers. So, initialize it as an empty array.
const [jobseekers, allUsers] = React.useState([]);

Set image in HTML from API request node.js

I have an API request that returns the image of the product that had been saved in the database in the form of buffer in MONGODB. The API returns the image and I want this image as source to my html element. How do I do that?
The API request is:
router.get('/product/avatar/:id', async (req, res) => {
try{
const product = await Product.findById(req.params.id)
if(!product || !product.avatar){
throw new Error()
}
// console.log('product avatar')
res.set('Content-Type', 'image/png')
res.send(product.avatar)
} catch(e) {
res.status(404).send()
}
})
And this is how I was trying to assign that image to my HTML
the code snippet given below is a part of the javascript used to render information on webpage from database.
var picId = data[i].name + 'Image'
// console.log(data[i]._id)
fetch('/product/avatar/'+data[i]._id, {
method: 'GET'
}).then((res) => {
return res.json()
}).then((data) => {
// picId.value = data
// document.getElementById(picId).src = data
console.log(data)
})

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