How do I display fetch response in react - reactjs

I want to display the response from my fetch request in react. So far, I built the fetch request and set up the useEffect and useState hooks. The response is an object. What am I doing wrong?
function App() {
const url = 'https://api.gemini.com/v1/book/btcusd'
const [orders, setOrders] = useState([])
const fetchData = () => {
fetch(url).then(response => {
return response.json();
}).then(data => {
console.log(data)
setOrders(data)
}).catch(error => {
console.log(error)
})
}
useEffect(() => {
fetchData()
}, [])
return (
<div className="App">
<h1>{orders.asks}</h1>
</div>
);
}
export default App;

Taking a quick look at that API, the asks property holds an array of objects. You would need to map those to JSX elements in order to display them.
Also, if orders is meant to be an object, you should not initialise it as an array.
Finally, you should always check the Response.ok property to see if the request resolved successfully.
// fetch-data.js
const url = "https://api.gemini.com/v1/book/btcusd";
export const fetchData = async () => {
const res = await fetch(url);
if (!res.ok) {
throw Object.assign(new Error(`${res.status}: ${res.statusText}`), {
url,
text: await res.text(),
});
}
return res.json();
};
// App.jsx
import { useEffect, useState } from "react";
import { fetchData } from "./fetch-data";
function App() {
// init with an object with empty `asks` array
const [orders, setOrders] = useState({ asks: [] });
useEffect(() => {
fetchData().then(setOrders).catch(console.error);
}, []);
return (
<div className="App">
{/* Map over the data */}
{orders.asks.map(({ price, amount }, i) => (
<dl key={i}>
<dt>Price</dt>
<dd>{price}</dd>
<dt>Amount</dt>
<dd>{amount}</dd>
</dl>
))}
</div>
);
}
export default App;

Your data is an object. You should use map to loop.
const url = "https://api.gemini.com/v1/book/btcusd";
const [orders, setOrders] = useState({ asks: [{price: 0, amount: 0}], bids: [{price: 0, amount: 0}] });
const fetchData = () => {
fetch(url)
.then((response) => {
return response.json();
})
.then((data) => {
console.log(data); //Data: {bids: Array(50), asks: Array(50)}
setOrders(data);
})
.catch((error) => {
console.log(error);
});
};
useEffect(() => {
fetchData();
}, []);
return (
<div className="App">
<table className="table">
<thead>
<th>Ask price</th>
<th>Ask amount</th>
<th>Bid price</th>
<th>Bid amount</th>
</thead>
{orders.asks?.map((e, i) => {
return (
<>
<tr>
<td>{e.price}</td>
<td>{e.amount}</td>
<td>{orders.bids[i].price}</td>
<td>{orders.bids[i].amount}</td>
</tr>
</>
)
})}
</table>
</div>
);

You Can use map function to display each item
eg:
orders.asks.map(item=>
<div>
<h1>{item.price}</h1>
<h1>{item.amount}</h1>
</div>
)

Related

React - show data from API - multiple requests

I have this simple React examle. Show data in React from API:
import React, { useEffect, useState } from "react";
const UsingFetch = () => {
const [users, setUsers] = useState([])
const fetchData = () => {
console.log('fetching');
fetch("https://jsonplaceholder.typicode.com/users")
.then(response => {
return response.json()
})
.then(data => {
console.log(data);
setUsers(data)
})
}
useEffect(() => {
fetchData()
}, [])
return (
<div>
{users.length > 0 && (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
)
}
export default UsingFetch
Why is in console twice: fetching and data from console.log?

How do I fetch the data from the API? I always get Undefined

I'm practising React with a small project where I want to display some Nba players but I don't get any data when trying to map an object.
I'm using this Api: http://data.nba.net/prod/v1/2022/players.json
Here is the code:
import React, { useEffect, useState } from "react";
const Players = () => {
const url = "http://data.nba.net/prod/v1/2022/players.json";
const [players, setPlayers] = useState([]);
useEffect(() => {
getPlayers();
}, []);
const getPlayers = async () => {
const api = await fetch(url);
const data = await api.json();
//wrapping a object into a array
setPlayers([data].flat());
};
return (
<div>
<h3>Sacramento player info</h3>
<ul>
{players.map((player) => (
<li key={player.league.sacramento.id}>
{player.league.sacramento.firstName}{" "}
{player.league.sacramento.lastName}{" "}
</li>
))}
</ul>
</div>
);
};
export default Players;
I recreated your code on codesandbox and it works just fine. I use other approach on getting data thru fetch and changed http:// to https://
const Players = () => {
const [data, setData] = useState(null);
function getAPIData() {
fetch("https://data.nba.net/prod/v1/2022/players.json")
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error("ERROR (response not ok)");
})
.then((data) => {
setData(data);
})
.catch((response) => {
console.log("error");
});
}
useEffect(() => getAPIData(), []);
return (
data && (
<div>
<h3>Sacramento player info</h3>
<ol>
{data.league.sacramento.map((player) => (
<li key={player.personId}>
{player.firstName} {player.lastName}
</li>
))}
</ol>
</div>
)
);
};
working code: https://codesandbox.io/s/players-info-51gf1w

I need to call two APIs in Reactjs

I have 2 APIs, one call the products and the other one call the image of the products.
Products API: https://inventory.dearsystems.com/ExternalApi/v2/Product
The second API is required call the ID of the products
Image API: https://inventory.dearsystems.com/ExternalApi/v2/product/attachments?ProductID=
How can I call the second one to show the image.
Here is my code:
import axios from "axios";
import { useEffect, useState } from "react";
import { SingleContent } from "../../components/SingleContent/SingleContent";
export const All = () => {
const [content, setContent] = useState([]);
const fetchAllProducts = async () => {
const { data } = await axios.get('https://inventory.dearsystems.com/ExternalApi/v2/Product',{
headers: {
"api-auth-accountid": process.env.REACT_APP_API_ID,
"api-auth-applicationkey": process.env.REACT_APP_API_KEY
}
});
console.log(data.Products);
setContent(data.Products)
}
useEffect(() =>{
fetchAllProducts();
}, [])
return (
<div>
<h1 className="pageTitle">All Products</h1>
<div className="all">
{content && content.map((c) =>
<SingleContent
key={c.id}
id={c.ID}
name={c.Name}
sku={c.SKU}
category={c.Category}/> )}
</div>
</div>
)
}
Inside fetchAllProducts() you could map the data.Products array you get from the first request, call the second api for each item and add the product image to the item.
Then you can update the contents with the resulting array.
Edited: example code below.
const fetchAllProducts = async () => {
const { data } = await axios.get('https://inventory.dearsystems.com/ExternalApi/v2/Product',{
headers: {
"api-auth-accountid": process.env.REACT_APP_API_ID,
"api-auth-applicationkey": process.env.REACT_APP_API_KEY
}
});
const productsWithImage = data.Products
.map(async product => {
const imageUrl = await axios.get("https://inventory.dearsystems.com/ExternalApi/v2/product/attachments?ProductID=" + product.id)
return {...product, imageUrl }
})
setContent(productsWithImage)
}
// Then you can use product.imageUrl when you map your products
Use for instead of map because it was returning a Promise. The problem is that if setContent(result) is called outside of the for, it only returns on register.
See the code:
export const AllHandle = () => {
const [content, setContent] = useState([]);
const fetchAllProducts = async () => {
const { data } = await axios.get("https://inventory.dearsystems.com/ExternalApi/v2/Product?limit=10",{
headers: {
"api-auth-accountid": process.env.REACT_APP_API_ID,
"api-auth-applicationkey": process.env.REACT_APP_API_KEY
}
});
let result = [];
const totaProducts = await data.Products;
for (let product of totaProducts) {
const imageUrl = await axios.get(`https://inventory.dearsystems.com/ExternalApi/v2/product/attachments?ProductID=${product.ID}`, {
headers: {
"api-auth-accountid": process.env.REACT_APP_API_ID,
"api-auth-applicationkey": process.env.REACT_APP_API_KEY
}
});
const imgUrl = imageUrl.data
result = [{ ...product, imgUrl}]
}
setContent(result)
}
useEffect(() =>{
fetchAllProducts();
}, [])
return (
<div>
<h1 className="pageTitle">All Products</h1>
<div className="all">
{content && content.map((c) =>
<SingleContent
key={c.ID}
id={c.ID}
name={c.Name}
sku={c.SKU}
category={c.Category}
attachment= { c.imgUrl[0].DownloadUrl}
/>
)}
</div>
</div>
)
}

How do use map function over array of objects in React

Having done the necessary to read the data using fetchAPI, I am having problems displaying the content because of the nature of the array.
import React, { useState, useEffect } from "react";
function Home() {
const [userData, setUserData] = useState([]);
async function getData() {
let response = await fetch("https://api.xxxxxxxx.io/something/students");
let data = await response.json();
return data;
}
//call getData function
getData().then((data) => console.log(data)); //
useEffect(() => {
getData()
.then((data) => {
setUserData(data);
})
.catch((error) => {
console.log(error);
});
}, []);
return (
<div>
{Object.keys(userData).map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
);
}
export default Home;
When I checked the console, the data are displayed but it is only showing students with no other data displayed.
I have the data below.
Try the following changes:
const [userData, setUserData] = useState({ students: [] });
...
return (
<div>
{userData.students.map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
);

NextJS how to fetch data after click event?

I have problem with load data to component after click on button.
I use getInitialProps to first load data on page.
How to load new data and past them to {data} after click?
export default function Users({ data }) {
const fetchData = async () => {
const req = await fetch("https://randomuser.me/api/?gender=male&results=100");
const data = await req.json();
return { data: data.results };
};
const handleClick = (event) => {
event.preventDefault();
fetchData();
};
return (
<Layout>
<button onClick={handleClick}>FETCH DATA</button>
{data.map((user) => {
return (
<div>
{user.email}
<img src={user.picture.medium} alt="" />
</div>
);
})}
</Layout>
);
}
Users.getInitialProps = async () => {
const req = await fetch(
"https://randomuser.me/api/?gender=female&results=10"
);
const data = await req.json();
return { data: data.results };
};
Thank a lot for help!
Use useState with the default value being the data you initially retrieved via getInitialProps:
import { useState } from 'React';
export default function Users({ initialData }) {
const [data, setData] = useState(initialData);
const fetchData = async () => {
const req = await fetch('https://randomuser.me/api/?gender=male&results=100');
const newData = await req.json();
return setData(newData.results);
};
const handleClick = (event) => {
event.preventDefault();
fetchData();
};
return (
<Layout>
<button onClick={handleClick}>FETCH DATA</button>
{data.map((user) => {
return (
<div>
{user.email}
<img src={user.picture.medium} alt="" />
</div>
);
})}
</Layout>
);
}
Users.getInitialProps = async () => {
const req = await fetch('https://randomuser.me/api/?gender=female&results=10');
const data = await req.json();
return { initialData: data.results };
};
Sidenote: Times have changed and it would seem that user1665355 is indeed correct:
Recommended: getStaticProps or getServerSideProps
If you're using Next.js 9.3 or newer, we recommend that you use
getStaticProps or getServerSideProps instead of getInitialProps.
These new data fetching methods allow you to have a granular choice
between static generation and server-side rendering.
import { useState } from 'React';
export default function Users({ initialData }) {
const [data, setData] = useState(initialData);
const fetchData = async () => {
const req = await fetch('https://randomuser.me/api/?gender=male&results=100');
const newData = await req.json();
setData(newData.results);
};
const handleClick = (event) => {
event.preventDefault();
fetchData();
};
return (
<Layout>
<button onClick={handleClick}>FETCH DATA</button>
{data.map(user => {
return (
<div key={user.login.uuid}>
{user.email}
<img src={user.picture.medium} alt="" />
</div>
);
})}
</Layout>
);
}
Users.getInitialProps = async () => {
const req = await fetch('https://randomuser.me/api/?gender=female&results=10');
const data = await req.json();
return { initialData: data.results };
};
I would like to list my notes about George's code. At least, it should pay attention to them.
First of all, it should attach any key to a div element otherwise a warning will have appeared in the browser console. Here is an article about using keys: https://reactjs.org/docs/lists-and-keys.html#keys
As well, the keyword return can be removed from the fetchData function that doesn't return a response.
It is recommended to use getStaticProps or getServerSideProps now. https://nextjs.org/docs/api-reference/data-fetching/getInitialProps

Resources