In my React app, I want to get the IP address of the user at client side. I intended to use ipify for that. When I'm using 'http://api.ipify.org/?format=json' in the browser, it successfully returns {"ip":"112.135.11.128"}, but I can't get the same response when I'm making request through fetch API. What I get is something like below.
code:
import React, { useEffect } from 'react';
const QRDisplay = () => {
async function getIP(){
const response = await fetch('https://api.ipify.org/?format=json');
const data = await response.json();
return response.status === 200 ? data : "err"
}
useEffect( () => {
getIP().then(data => console.log(data))
},[])
return (
<>
</>
);
};
export default QRDisplay;
You need to call .json() method to get body.
async function getIP(){
const response = await fetch('http://api.ipify.org/?format=json');
const data = await response.json();
return data;
}
Then you can use it like so:
getIP().then(data => console.log(data);
Similar approach to Ozan Bulut
await fetch('http://api.ipify.org/?format=json')
.then(response => response.json())
.then(data => {
/* use data here */
});
Related
I'm trying to create an API function with a help of React Query and Axios.
When I'm using useQuery with vanilla fetch function - it all works perfectly.
export const useGetDebts = async () => {
const { families } = appStore.user;
const res = useQuery("getDebts", async () => {
const res = await fetch(`${API_URL}/api/family/${families[0]}/debts`, {
method: "GET",
headers: {
Authorization: `Bearer ${appStore.token ?? ""}`,
},
});
const parsedBody: DebtsResponse = await res.json();
return parsedBody;
});
return res;
};
But when I switch the vanilla fetch function to Axios - I get an error status of 500 (not sure if it comes from React Query or Axios).
export const useGetDebts = async () => {
const { families } = appStore.user;
const res = useQuery("getDebts", async () => {
const res = await axiosInstance.get<DebtsResponse>(`/api/family/${families[0]}/debts`);
return res.data;
});
return res;
};
Thanks in advance for any explanations/suggestions.
P.s. The axiosInstance works fine with the useMutation hook. So it only makes me more confused. =(
export const useGetDebt = () => (
useMutation(async (id: number) => {
const { families } = appStore.user;
const res = await axiosInstance.get<DebtResponse>(`/api/family/${families[0]}/debts/${id}`);
return res.data;
})
);
P.s.s. I'm working with React Native if it's somehow relevant.
react-query doesn't give you any 500 errors because react-query doesn't do any data fetching. It just takes the promise returned from the queryFn and manages the async state for you.
I'm not sure if the fetch code really works because it doesn't handle any errors. fetch does not transform erroneous status codes like 4xx or 5xx to a failed promise like axios does. You need to check response.ok for that:
useQuery(['todos', todoId], async () => {
const response = await fetch('/todos/' + todoId)
if (!response.ok) {
throw new Error('Network response was not ok')
}
return response.json()
})
see Usage with fetch and other clients that do not throw by default.
So my best guess is that the fetch example also gives you a 500 error code, but you are not forwarding that error to react-query.
Hi i wanna make an api call which depends another API. One API give me the ID from a random movie, and the second give me the details about that movie. All is separated in a file api.js and exported to a component. If i export the function i get a Promise how is fullfilled but not the movie details. How can i resolve this nested API? Here is the code if its help
export async function getMovieDetail() {
const data = await fetch(`https://api.themoviedb.org/3/trending/all/day?
api_key=${apiKey}`).then((res) => res.json());
const movie = data.results[random].id;
async function getMovieById() {
const data = await fetch(`https://api.themoviedb.org/3/movie/${movie}?
api_key=${apiKey}&language=en-US`).then((res) => res.json());
return data;
}
const movieDetail = await getMovieById();
return movieDetail;
}
chain both requests like this
export async function getMovieDetail() {
return fetch(`https://api.themoviedb.org/3/trending/all/day?
api_key=${apiKey}`)
.then((res) => res.json())
.then((data) => {
const movie = data.results[random].id;
return fetch(`https://api.themoviedb.org/3/movie/${movie}?
api_key=${apiKey}&language=en-US`)
}).then((res) => res.json());
}
I'm very much new to react native currently i'm building small app for just getting an idea about this. I'm facing an issue in mapping the data from API. This is the json response returning from the api
{"data":[{"digit":300,"countsum":"52"},{"digit":301,"countsum":"102"},{"digit":302,"countsum":"27"},{"digit":303,"countsum":"201"},{"digit":500,"countsum":"101"}]}
When i tried to map this data i'm facing some issues. I stored the response from API to the state and when i tried to display the state data using map function it's showing the state value is null. This the code i tried till now
const [listdata, setListData] = useState(null)
useEffect(() => {
// Run! Like go get some data from an API.
getListData();
}, []);
const getListData = async () => {
const token = await AsyncStorage.getItem("#userToken")
axios
.get(constants.BASE_URL + "getlist?token=" +token)
.then(response => setListData(response.data))
.catch(error => {
console.log(error);
});
listdata.map(item => <Text>{item.digit}</Text>)
}
Do it like this,
export default function ComponentName () {
const [listdata, setListData] = useState([])
useEffect(() => {
// Run! Like go get some data from an API.
getListData();
}, []);
const getListData = async () => {
const token = await AsyncStorage.getItem("#userToken")
axios
.get(constants.BASE_URL + "getlist?token=" +token)
.then(response => setListData(response.data))
.catch(error => {
console.log(error);
});
}
return (<>
listdata.map(item => <Text>{item.digit}</Text>)
</>
);
}
You have to wait the fetch execution and later do the list map.
// wait for it
await axios
.get(constants.BASE_URL + "getlist?token=" +token)
.then(response => setListData(response.data))
.catch(error => {
console.log(error);
});
listdata.map(item => <Text>{item.digit}</Text>)
If you want to map the data then do that inside return statement of your code ,like:
return(
{listData?listdata.map(item => return <Text>{item.digit}</Text>):""}
);
This is a sample of a meant in my comment above:
Try console.log listdata at this stage, you will find that it is still
null, in other words, the value of the updated value of the
listdata:useSate will be ready after the render take place. You can
make another function outside of the current one. then use useEffect
with listdata to update your text views
const [listdata, setListData] = useState(null)
useEffect(() => makeRemoteRequest(), [listdata])
makeRemoteRequest = () => {
const url = `your-url-of-data-here`;
fetch(url)
.then(res => res.json())
.then(res => {
setListData(res.data);
})
.catch(error => {
console.log(error)
});
};
You could try the following:
const [listdata, setListData] = useState([])
useEffect(() => {
// Run! Like go get some data from an API.
getListData();
}, []);
const getListData = async () => {
const token = await AsyncStorage.getItem("#userToken")
try {
const dataResponse = await axios.get(constants.BASE_URL + "getlist?token=" +token);
setListData(dataResponse.data || [] );
} catch(error) {
console.log(error);
}
}
return (<>
listdata.map(item => <Text>{item.digit}</Text>)
</>);
Beginner with react and struggling with something that I am sure is probably very simple. I am just trying to make a simple component that will fetch data and display a part of it in a div. I am able to get the data and print it to console, but I am having trouble saving to a variable and displaying it. Here is my code (removed the actual url for privacy reasons):
let x = -1;
function getData(apiUrl){
fetch(apiUrl, {credentials: 'same-origin'})
.then((response) => {
if (!response.ok) {
Logging.error(`Did not get an ok. got: ${response.statusText}`);
}
return response.json();
})
.then(json => {x = json.value})
.catch((error) => {
Logging.error(`Error getting ad data: ${error.message}`);
})
}
const MyPage = () => {
getData('my endpoint')
return (
<div>{x}</div>
);
}
My issue is when I load the page it always displays my default value of "-1". So either x is never getting re-assigned, or the return is happening before it does.
Other commenters about setting state is not wrong.
However, you are also not exactly wrong, expecting a value for x.
Your getData function calls fetch, however you did not return anything from fetch. If you want to use x = getData(), you will need to ensure to add a return before the fetch function in order to return the data.
const getData = (apiUrl) => {
return fetch(apiUrl, {credentials: 'same-origin'})
.then((response) => {
if (!response.ok) {
Logging.error(`Did not get an ok. got: ${response.statusText}`);
}
return response.json();
})
.then(json => {x = json.value})
.catch((error) => {
Logging.error(`Error getting ad data: ${error.message}`);
})
}
let x = await getData(apiUrl)
However, fetch is asynchronous so it's you need to use x = await getData().
You cannot use await outside an async function, so you need to use effect, and useState to properly render the data you want.
import React, { useEffect, useState } from 'react';
const MyPage = () => {
const [ data, setData ] = useState();
useEffect(() => {
getData(apiUrl);
},[])
const getData = async (apiUrl) => {
fetch(apiUrl, {credentials: 'same-origin'})
.then((response) => {
if (!response.ok) {
Logging.error(`Did not get an ok. got: ${response.statusText}`);
}
return response.json();
})
.then(json => setData(json)) //setData here
.catch((error) => {
Logging.error(`Error getting ad data: ${error.message}`);
})
}
return (<pre>{ JSON.stringify(data, null, 4)}</pre>)
}
You need to use JSON.stringify to show your JSON results in your return statement.
You need to you use the state in react. Try something like:
import react, { useState, useEfect } from 'react';
const MyPage = () => {
const [data, setData] = useState(null);
const useEfect(() => {
const result = getData('my endpoint');
setData(result);
}, []);
return (
<div>{data}</div>
);
}
im trying to make a request to google api but returns me network error. If i put the url in the browser, brings me the information correctly.I tryed to formate the request without success. The google places search works correctly too.
export const fetch_information = (skip, limit, filter) => async (dispatch) => {
try {
var url = `https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJk0aJYPbk3JQRLpKN20Jecko&fields=name,rating,formatted_phone_number&key=MyKey`;
const {data} = await axios.get(url)
console.log(data)
} catch (error) {
console.log(error.message)
}
}
and
export const fetch_information = (skip, limit, filter) => async (dispatch) => {
try {
var url = `https://maps.googleapis.com/maps/api/place/details/json?`;
let config = {
params: {
place_id: 'ChIJk0aJYPbk3JQRLpKN20Jecko',
key: 'myKey',
},
}
const {data} = await axios.get(url, config)
console.log(data)
} catch (error) {
console.log(error.message)
}
}
I think that the request looks a bit messy. I'm under the impression that you are trying to pass results to a redux store. Let's see if we can clean this up a bit.
export const fetch_information = async () => dispatch => {
const req = await axios.get("https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJk0aJYPbk3JQRLpKN20Jecko&fields=name,rating,formatted_phone_number&key=MyKey");
const data = await req.json();
return data;
//or, for your purpose...
console.log(data);
//can also dispatch for store
}
I didn't see anything you were passing as necessary for this.