How to print json api data in reactjs - json

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([]);

Related

How to pass updated set State value in axios request as params

I'm a beginner in react native, I'm trying to get user information from mysql database through an axios API get request.
Once logged in, I stored email address in AsyncStorage and later want to use that email address from AsyncStorage as params or parameters to get the user details.
I wrote a code which set initial state of the setState as 'na'. Please help me how I can pass the email address from AsyncStorage as params or parameters.
Here is my code.
// to load email address
const [SessionEmail, setSessionEmail] = useState('na');
// to load users info
const [users, setUsers] = useState([]);
useFocusEffect(
React.useCallback(() => {
getUsername();
getUsersInfoFromAPI();
}, [])
);
// to get the session username from localstorage
const getUsername = async () => {
try {
const username = await AsyncStorage.getItem('Username')
if (username !== null) {
setSessionEmail(username);
}
} catch (e) {
console.log(e);
}
}
// API Calling user details
const getUsersInfoFromAPI = async () => {
await axios.get(`https://myapi.co.in/api/user/?email=${SessionEmail}`)
.then(response => {
setUser(response.data);
})
.catch(error => {
console.log(error);
});
}
After the page is rendered, and I load page from metro, I can see the parameters have been sent to server.
Update your code in this way:
useFocusEffect(
React.useCallback(() => {
getUsername();
}, [])
);
Instead of saving your email to state, sent it to function directly but if you are using it for other reason you can still save it but call function while getting username from AsyncStorage with username parameter like below.
// to get the session username from localstorage
const getUsername = async () => {
try {
const username = await AsyncStorage.getItem('Username')
if (username !== null) {
getUsersInfoFromAPI(username);
}
} catch (e) {
console.log(e);
}
}
// API Calling user details
const getUsersInfoFromAPI = async (email) => {
await axios.get(`https://myapi.co.in/api/user/?email=${email}`)
.then(response => {
setUser(response.data);
})
.catch(error => {
console.log(error);
});
}
const [users, setUsers] = useState([]);
here you can use like this
const [users, setUsers] = useState();
hope this will help you

Getting responses from two interdependent JSON generates an error [React Hooks]

I want to download the data first about the city in which the user is located from ipstack.com and then use this information to generate the weather using openweather.com. However, the following problem occurs during render:
Test.js:20 GET https://api.openweathermap.org/data/2.5/weather?lat=undefined&lon=undefined&units=metric&appid=(MY API KEY) 400 (Bad Request)
The problem is strange because the data I require appears in state eventually:
My code:
import React, { useState, useEffect } from 'react';
const Test = () => {
const [place, setPlace] = useState([]);
const [weather, setWeather] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(false)
fetch(`http://api.ipstack.com/check?access_key=(MY API KEY)`)
.then(result => result.json())
.then(json => {
setPlace([json.latitude, json.longitude, json.region_name])
})
.catch(err => {
console.log("Error " + err);
})
}, [])
useEffect(() => {
fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${place[0]}&lon=${place[1]}&units=metric&appid=(MY API KEY)`)
.then(result => result.json())
.then(json => {
setWeather(json)
})
.catch(err => {
console.log("Error " + err);
setLoading(true);
})
}, [place])
return (
<>
{loading && (
<>
<p>{place[0]}</p>
<p>{place[1]}</p>
<p>{place[2]}</p>
<p>{weather.name}</p>
</>
)}
</>
);
}
export default Test;
I think in the second effect you should fetch data from openweathermap.org only if place array assigned and has correct data. Otherwise on first run you will send invalid data (undefineds instead of positions)

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

Why is this promise returning an [object Promise] and not the value?

I thought I fully understood promises, but I'm stumped on this. I realize I should use async/await, but for this example I specifically want to only use .then().
When I do this:
const theJson = fetch(
`https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/quotes.json`
)
.then( quoteTypeResponse => quoteTypeResponse.json() )
.then( data => {
console.log(data)
return data
});
the console.log(data) in the last function prints the JSON as expected, but when I try to console.log(theJson), the returned value, it prints [object Promise].. Why is this?
I was able to get the data outside of the function using react's useState/useEffect but not with just a vanilla global variable. I'm not trying to solve anything, but just want to understand why this does not work.
export default function App() {
let globalVar;
const [theQuote, setTheQuote] = useState({});
useEffect(() => {
fetch(`https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/quotes.json`)
.then(quoteTypeResponse => quoteTypeResponse.json())
.then(quoteType =>
fetch(
'https://programming-quotes-api.herokuapp.com/quotes/' +
quoteType.type
)
)
.then(quoteResponse => {
return quoteResponse.json();
})
.then(quote => {
setTheQuote({ quote: quote.en, author: quote.author });
globalVar = quote.author;
});
}, []);
return (
<div id="app">
<h1>{theQuote.quote}</h1> // renders
<h2>{theQuote.author}</h2> // renders
<h3>globalVar: {globalVar}</h3> // undefined
</div>
);
}
Because your second .then() is inside the first then(), so theJson is a Promise<T>. The nice thing about Promise<T> is that you can move an inner .then() call up a level and it will still work:
Change it from this:
const theJson = fetch(
`https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/quotes.json`
)
.then( quoteTypeResponse => quoteTypeResponse.json().then( data => {
console.log(data)
return data
} )
);
To this:
const theJson = fetch(
`https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/quotes.json`
)
.then( quoteTypeResponse => quoteTypeResponse.json() )
.then( data => {
console.log(data)
return data
});
But ideally, use async function so you can have this considerably simpler code instead:
const resp = await fetch( `https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/quotes.json` );
const data = await resp.json();
console.log( data );
#pushkin left a good link explaining the differences between async/await and using .then(), but basically, the value returned by the then() is only available within that block.
Promises cheat sheet: https://levelup.gitconnected.com/async-await-vs-promises-4fe98d11038f
fetch(`https://s3-us-west-2.amazonaws.com/s.cdpn.io/28963/quotes.json`)
.then(quoteTypeResponse => quoteTypeResponse.json())
.then(quoteType =>
fetch(
'https://programming-quotes-api.herokuapp.com/quotes/' + quoteType.type
)
)
.then(quoteResponse => {
return quoteResponse.json();
})
.then(quote => {
console.log(`q:${util.inspect(quote)}`);
document.getElementById('app').innerHTML = quote.en;
});

How to fix Cannot set headers after they are sent to the client?

After reading up on this topic for the last 2.5 hours I cant determine how to fix my: Cannot set headers after they are sent to the client issue, but I think it has to do with the below code at the bottom especially the code is in bold.
Any help or assistance will be greatly appreciated.
app.post("/api/tracking/retrieve", (req, res) => {
res.setHeader('Content-Type', 'application/json');
// before all the iterations
const trackingCodes = ['EZ6000000006', 'EZ4000000004'];
const carrierCodes = ['UPS', 'UPS'];
trackingCodes.forEach((trackingCode) => {
carrierCodes.forEach((carrierCode) => {
const tracker = new api.Tracker({
tracking_code: trackingCode,
carrier: carrierCode
})
tracker.save().then(function (data) {
table = 'tracking_table';
col = ['user_id', 'tracking_number'];
val = [user_id, tracker.tracking_code];
**// !ISSUE: :: ::: :::: ::::: :::::: ::::::: //**
main.create(table, col, val, function (data) {
res.send(JSON.stringify({
id: "",
user_id: user_id,
tracking_number: data.tracking_code
})); // replace this for your res.json()
});
}
)
.catch(error => {
// handle errors
console.log('There has been an error with your submission.')
});
})
})
res.end()
});
As #kiran Mathew has answered, the res.json() are called again and again inside for loop which is why 'cannot set headers after response sent' occurs.
You could have a result array 'trackingNumbers' to store all tracking_number and later exiting from the loop, sent a single response.
app.post("/api/tracking/retrieve", (req, res) => {
const trackingCodes = ["EZ6000000006", "EZ4000000004"];
const carrierCodes = ["UPS", "UPS"];
const trackingNumbers = [];
trackingCodes.forEach(trackingCode => {
carrierCodes.forEach(carrierCode => {
const tracker = new api.Tracker({
tracking_code: trackingCode,
carrier: carrierCode
});
tracker
.save()
.then(function(data) {
table = "tracking_table";
col = ["user_id", "tracking_number"];
val = [user_id, tracker.tracking_code];
// !ISSUE: :: ::: :::: ::::: :::::: ::::::: //**
main.create(table, col, val, function(data) {
// res.json({
// id: "",
// user_id: user_id,
// tracking_number: data.tracking_code
// });
trackingNumbers.push(data.tracking_code);
});
})
.catch(error => {
// handle errors
console.log("There has been an error with your submission.");
});
res.json({
id: "",
user_id: user_id,
tracking_number: trackingNumbers
});
});
});
});
The issue with your code is you are calling res.json() in an iterative loop.
You should call that only once since
res.json() implements res.write(),res.setHeaders() and res.end() under the hood,
which means once res.end() is called it ends the request and cannot send anymore.
You are better off writing the responses using
res.setHeader('Content-Type', 'application/json'); // before all the iterations
res.send(JSON.stringify({key:"value"})); // replace this for your res.json()
res.end() // after iterations