I'm having a recurrent problem with react query. On some queries, the query says "fetching" (blue color), but the request to the server "doesn't go through". It's "suspended" or something. And I tried console.logging on my nodeJS controller (associated with the GET endpoint), but the function isn't even called.
This is quite annoying (and to be clear, this is with new queries which aren't stale or cached).
This is my query:
const postDetails = useQuery(
["post", postId],
async () =>
await fetch(
"http://localhost:5000/api/post/id/" + postId
).then((res) => res.json()),
{
onSuccess: (data) => {
console.log(data);
},
}
);
This is what React Query Devtools says:
This is what the network tab says:
Thanks in advance.
I believe your use of await and .then is giving you issues. I would recommend just sticking with await
const postDetails = useQuery(
["post", postId],
async () =>
try {
let res = await fetch(
"http://localhost:5000/api/post/id/" + postId
)
res = await res.json()
} catch(err) {
console.error(err)
}
{
onSuccess: (data) => {
console.log(data);
},
}
);
This method uses a trycatch for error handling, and does not rely on .then which I believe is where the issue lies.
Try separating the fetch function from the query:
async function fetchPosts() {
try {
const res = await fetch(
"http://localhost:5000/api/post/id/" + postId
)
const json = await res.json()
return json
} catch (err) {
console.error(err)
}
}
const postDetails = useQuery(
["post", postId],
fetchPosts,
{
onSuccess: (data) => {
console.log(data);
},
}
);
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.
I'm trying to fetch from the PokemonAPI but when I console.log my response, it logs twice, and I don't know if that's a problem or not. I'm doing it with Reactjs. My code:
const fetchPokemon = async () => {
try {
const res = await fetch('https://pokeapi.co/api/v2/pokemon/1')
const pokemon = await res.json()
console.log(pokemon)
} catch (err) {
console.log(err)
}
}
fetchPokemon()
In React functional components API call should be placed inside useEffect() function, this will resolve your issue.
useEffect(() => {
async function apiCall() {
const res = await fetch('https://pokeapi.co/api/v2/pokemon/1')
const pokemon = await res.json()
console.log(pokemon)
}
apiCall();
}, []);
I'm working with redux and I am trying to fetch Star War API.
Here is my code:
import { MOVIES_ERROR, MOVIE_CHARACTERS } from "./types";
// Get all characters
export const getCharacters = (userId) => async (dispatch) => {
try {
const res = await fetch(`https://swapi.dev/api/films/${userId}`);
if (!res.ok) {
throw new Error("sometheing went wrong");
}
const getData = await res.json();
const characters = await getData.characters;
let people = [];
Promise.all(
characters.map((url) =>
fetch(url)
.then((response) => response.json())
.then((name) => people.push(name))
)
);
dispatch({
type: MOVIE_CHARACTERS,
payload: people,
});
} catch (err) {
dispatch({
type: MOVIES_ERROR,
payload: { msg: err.response.statusText, status: err.response.status },
});
}
};
when I make a console log inside a promise. all I got people array filled with all the data, but when I dispatch it I got an empty array in the reducer. can anyone tell me what the mistake that i did?
I got the problem just now, I need to add await before Promise.all :)
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.
I am trying to fetch data and set the state in React App. While the fetch is successful, as I can see the data in chrome dev tools, the execution stops at await statement in the below code. Only "getting data" is logged. Looks like after fetch statement the function returns, with all the following steps running successfully.
What am I doing wrong??
Any kind of help is much appreciated.
import util from "util";
const fetchProm = util.promisify(fetch)
....
getDataFromDb = async () => {
console.log('getting data')
let result = await fetchProm("http://localhost:3001/getData")
.then(data => {
console.log("then1:",data)
return data.json()
})
.then(res => {
console.log('then2:', res.data)
return { data: res.data }
})
.catch(err => {
return { err: err.data }
});
console.log("result:", result)
this.setState({ data: result.data })
};
you do not need .then callback if you use async-await.
try below sample :
import util from "util";
const fetchProm = util.promisify(fetch)
getDataFromDb = async () => {
console.log('getting data')
let {data} = await fetchProm("http://localhost:3001/getData");
console.log("result:", data)
this.setState({ data })
};
With async/wait you don't need the then. Also you catch errors on the second then and not the first.
Can you try:
let result = await fetchProm("http://localhost:3001/getData")
console.log(result)
and see if it works?
When using async/await, don't forget to handle your exceptions with try/catch
Change your code to:
import util from "util";
getDataFromDb = async () => {
try{
let {data} = await fetchProm("http://localhost:3001/getData");
this.setState({ data })
}
catch(err=> this.setState({ err: err.data }))
};