React-query not making the requests - reactjs

After doing some research on why I'm getting an undefined I noticed that no requests are being executed for some reason (chrome, "Network" tab shows no requests made to /admin/cafes).
At the moment, my code looks like this:
CafesTable.js
const fetchCafes = async () => {
const res = await apiClient.get("/admin/cafes");
return res;
};
function CafesTable() {
const { data, status } = useQuery("cafes", fetchCafes);
console.log(data);
the apiClient makes reference to:
const token = "Bearer " + Cookies.get("token");
export default axios.create({
baseURL: `${process.env.REACT_APP_API_ENDPOINT}/api`,
headers: {
Authorization: token,
},
});
which is inside http-common.js
Still, nothing is happening. Any idea why?

As #AdamThomas suggested, the syntax changed for the newest version.
I refactored the code, and it now works. It looks like this:
const { data, status } = useQuery(["cafes"], () =>
fetchCafes.then((res) => res.json())
);

Related

Accessing Data from my axios get response not working

can someone point out where am going wrong?
I have a simple API get request. this get data fine from my API
const GetMedicalPackages = async (props:IGetMedPack)=>{
const token = props.token
const data = axios({
method:"get",
responseType:"json",
url : baseURL + "medicalPackage",
headers: { "Authorization": `Bearer ${token}`}
})
await data;
return data.then((response:IMedicalPackageData| undefined)=>{
return response
})
}
This returns data like this
Data from API
Now trying to access the data with this code returns with this code always returns and undefined
useEffect(() => {
//async function fetchMyData() {
GetMedicalPackages({ token }).then((response) => {
if (response) {
const options = response.data.map((row) => {
console.log(row.MedicalInsurancePackage);
return row.MedicalInsurancePackage;
//console.log(row);
//options.push(row.MedicalInsurancePackage);
});
//setMedPackage(options);
console.log(options, response.data);
}
});
options values
I suspect it to do with the object that returned in each row but i might be wrong.
Can someone point out what is wrong please thanks
I have tried foreach and various techniques but nothing.
to get the array of strings
Just for clarity, The problem is not the axios call giving me the data. I can see data fine. But try to use the data returned is the problem. console log shows me the data. but as soon i try to map it i get undefines. Please see images
console log row give me this
activePackage: true
medicalInsurancePackage: "Standard"
medicalInsurancePackageDesc: "S Standard"
medicalInsurancePackageID:1
[[Prototype]]:Object
but console log row.medicalInsurancePackage give me undifined
Looks like your are missunderstanding how Promise are working. consider doing:
const GetMedicalPackages = async (props) => {
const token = props.token;
return await axios({
method: "get",
responseType: "json",
url : baseURL + "medicalPackage",
headers: { Authorization: `Bearer ${token}` },
});
};
You shouldn't be awaiting your variable, but should be awaiting for the result of your axios call. And then just return the response you get from it.
const data = await axios(...)
return data;

sessionStorage not available immediately after navigate

I am trying to implement an React solution with Strapi as backend where authorization is done using JWT-keys. My login form is implemented using the function below:
const handleLogin = async (e) => {
let responsekey = null
e.preventDefault();
const data = {
identifier: LoginState.username,
password: LoginState.password
}
await http.post(`auth/local`, data).then((response) => {
setAuth({
userid: response.data.user.id,
loggedin: true
})
responsekey = response.data.jwt
setLoginState({...LoginState, success: true});
sessionStorage.setItem('product-authkey', responsekey);
navigate('/profile');
}).catch(function(error) {
let result = ErrorHandlerAPI(error);
setLoginState({...LoginState, errormessage: result, erroroccurred: true});
});
}
The API-handler should return an Axios item which can be used to query the API. That function is also shown below. If no API-key is present it should return an Axios object without one as for some functionality in the site no JWT-key is necessary.
const GetAPI = () => {
let result = null
console.log(sessionStorage.getItem("product-authkey"))
if (sessionStorage.getItem("product-authkey") === null) {
result = axios.create(
{
baseURL: localurl,
headers: {
'Content-type': 'application/json'
}
}
)
} else {
result = axios.create({
baseURL: localurl,
headers: {
'Content-type': 'application/json',
'Authorization': `Bearer ${sessionStorage.getItem("product-authkey")}`
}
})
}
return result
}
export default GetAPI()
However, once the user is redirected to the profile page (on which an API-call is made which needs an JWT-key), the request fails as there is no key present in the sessionStorage. The console.log also shows 'null'. If I look at the DevTools I do see that the key is there... And if I refresh the profile page the request goes through with the key, so the key and backend are working as they should.
I tried making the GetAPI function to be synchronous and to move the navigate command out of the await part in the handleLogin function, but that didn't help.
Does someone have an idea?
Thanks!
Sincerely,
Jelle
UPDATE:
Seems to work now, but I need to introduce the getAPI in the useEffect hook, I am not sure if that is a good pattern. This is the code of the profile page:
useEffect(() => {
let testapi = GetAPI()
const getMatches = async () => {
const response = await testapi.get(`/profile/${auth.userid}`)
const rawdata = response.data.data
... etc
}, [setMatchState]
export default GetAPI() this is the problematic line. You are running the GetApi function when the module loads. Basically you only get the token when you visit the site and the js files are loaded. Then you keep working with null. When you reload the page it can load the token from the session storage.
The solution is to export the function and call it when you need to make an api call.

onSuccess callback in Plaid Link not updating

I've built a PlaidLink component using react-plaid-link as below. There's no issues when building with the standard way - passing in only public_token and account_id to the request body.
However, when I attempt to pass in stripeUid to the request body, only an empty string (the initial value of the stripeUid state) is passed. This is despite the value of stripeUid being updated and passed in correctly from the parent via props. For some reason stripeUid does not update within the useCallback hook even though the value is in the dependency array.
Any idea why the value is not updating?
function PlaidLink(props) {
const [token, setToken] = useState("");
const { achPayments, stripeUid } = props;
async function createLinkToken() {
const fetchConfig = {
method: "POST",
};
const response = await fetch(
API_URL + "/plaid/create-link-token",
fetchConfig
);
const jsonResponse = await response.json();
const { link_token } = jsonResponse;
setToken(link_token);
}
const onSuccess = useCallback(
(publicToken, metadata) => {
const { account_id } = metadata;
// Exchange a public token for an access one.
async function exchangeTokens() {
const fetchConfig = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
public_token: publicToken,
account_id,
stripeUid,
}),
};
const response = await fetch(
API_URL + "/plaid/exchange-tokens",
fetchConfig
);
const jsonResponse = await response.json();
console.log("Exchange token response:", jsonResponse);
}
exchangeTokens();
}, [stripeUid]
);
const { open, ready } = usePlaidLink({
token,
onSuccess,
});
// get link_token from your server when component mounts
useEffect(() => {
createLinkToken();
}, []);
useEffect(() => {
if (achPayments && ready) {
open();
}
}, [achPayments, ready, open]);
return <div></div>;
}
export default PlaidLink;
I am not familiar with Stripe API but from reading a code I see a possible issue with the code.
Following the chain of events, there is one usePlaidLink and two useEffects. When the component mounts, it createLinkToken in one of the effects and open in the other (assuming it is ready).
However, when stripeUid changes, it doesn't re-fire the effects. So, that's a hint for me.
Next, checking the source of usePlaidLink here: https://github.com/plaid/react-plaid-link/blob/master/src/usePlaidLink.ts gives me an idea: it doesn't do anything when options.onSuccess changes, only when options.token changes. This is their dependency array:
[loading, error, options.token, products]
So it looks like your code is correct as far as effects in react go, but it doesnt't work together because changing the onSuccess doesn't do anything.
How to solve:
make a pull request into the open source library to fix the issue there
inline that library into your code and fix it for yourself
use "keyed components" to unmount and mount the component again when the uid changes instead of updating to work around the issue
some other solution

React Query useQuery & Axios

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.

Code after fetch call is seemingly not read

I'm making a POST request to a local Express server with a JSON as its body and I'm doing this inside an async function:
async function sendSigninForm(login_form) {
const settings = {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(login_form)
};
try {
await fetch(`http://localhost:9000/signin`, settings)
} catch (e) {
return e;
}
}
I tried accessing fetch's response in various ways, like
const fetchResponse = await fetch(`http://localhost:9000/signin`, settings);
const data = await fetchResponse.json();
or
const fetchResponse = await fetch(`http://localhost:9000/signin`, settings)
.then((value) => console.log(value));
but neither of these work, and I can't even print anything.
const fetchResponse = await fetch(`http://localhost:9000/signin`, settings)
.then(console.log("hello"));
This works, but of course it won't let me print fetch's response so it's useless to me. Also, the server is apparently working correctly as it gets the form as required and queries the database correctly.
Well, I forgot to send status codes server-side, and apparently that's the reason it hanged, although everything seemed to be fine and the queries were actually executed.

Resources