I am stuck and looking for someone to help me. I've been trying to Authorize my fetch request but it always return an error. Is there someone who could explain in what way authorize header?
import { ref } from "vue";
const getAllData = () => {
const data = ref();
const entry = "user:pass";
const fetchAllData = async function () {
const res = await fetch("http://127.0.0.1:8000/articles/", {
method: "GET",
headers: {
// How to authorize?
Authorization: Bearer ${entry},
},
});
data.value = await res.json();
console.log(data.value);
};
return { data, fetchAllData };
};
export default getAllData;
Related
on this nextjs project i'm fetching data from an api and it's logging successfully. but i just can't seem to render the response (from the handleSubmit const) on my main jsx return. i try it as {cart.categoryTitle} and i got no error, but also no render on my app. am i doing something wrong? thanks!
import { useEffect, useState } from "react";
const Lista = () => {
const [categoryTitle, setCategoryTitle] = useState<any>();
const [cart, setCart] = useState([])
interface Data {
id: number;
title: string;
}
useEffect(() => {
handleCategoryData();
}, []);
async function handleCategoryData() {
const response = await fetch("/api/category");
const categoryTitle = await response.json();
setCategoryTitle(categoryTitle);
}
const handleSubmit = async (event: any) => {
event.preventDefault();
const categoryTitle = event.target[0].value;
const sub = event.target[1].value;
const name = [event.target[2].value];
const type = event.target[3].value == "Unidade" ? "unit" : "kg";
const price = event.target[4].value;
const counter = event.target[5].value;
//const img = event.target[6].value;
const res = await fetch("../api/list", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
products: [
{
categoryTitle,
sub,
name,
type,
price,
quantity,
},
],
}),
});
const response = await res.json();
console.log(response);
// return JSON.stringify(response);
setCart(response)
};
if (!categoryTitle) return <p>Loading</p>;
if (!sub) return <p>Loading</p>;
if (!productResponse) return <p>Loading</p>;
return (
<>
<section>
<div className="listsContainer">
<div className="cartContainer">
<div className="listText">
<p>Lista</p>
<p>{cart.categoryTitle}</p>
<p>0 categorias / 0 itens</p>
</div>
</div>
What does the response look like? Is it an object that has categoryTitle property? It may be the case that there’s no categoryTitle in the response object. Your cart state is being initialize as an array so maybe you are expecting the response to be an array as well?
i'M working on a Chat Application project
but im getting this error of fetching friends from the backend(node)
I'm getting the friends data on the console but i'm unable to display it.
this is my Context and States
export const Messenger = () => {
// Context State
const { friends, setFriends, authInfo } = useAuth();
const [loggedUser, setLoggedUser] = useState();
const { updateNotification } = useNotification();
const fetchMessengerUsers = async () => {
try {
const token = getToken();
const config = {
headers: {
authorization: "Bearer " + token,
},
};
const { data } = await client("/get-friends", config);
console.log(data);
setFriends(data);
} catch (error) {
updateNotification("error", "Failed To load the Chat");
}
};
useEffect(() => {
setLoggedUser(localStorage.getItem("auth-token"));
fetchMessengerUsers();
}, []);
then in return i'm mapping all friends to display them
<div className="friends">
{friends && friends.length > 0
? friends.map((fd) => (
<div className="hover-friend">
<Friends friend={fd} />
</div>
))
: "No Friend"}
</div>
It displays No Friend on the browser
this link shows how it appears on the browser
just change your fetchMessengerUsers function.
you need to set setFriends(data.friends)
const fetchMessengerUsers = async () => {
try {
const token = getToken();
const config = {
headers: {
authorization: "Bearer " + token,
},
};
const { data } = await client("/get-friends", config);
console.log(data);
setFriends(data.friends); // you have to set friends array here, earlier you were setting the entire object.
} catch (error) {
updateNotification("error", "Failed To load the Chat");
}
};
I have external .js file created exactly for fetching data from backend based on website locale. Here is the code:
import { ref } from "vue";
export function fetchData(section, key) {
// GET request using fetch with error handling and headers
const headers = {
method: "GET",
headers: { "Content-Type": "application/json" },
};
const fetchedData = ref(null);
fetch(
"http://localhost:4000/api/" + section + "/?api-key=" + key,
headers
)
.then(async (response) => {
const data = await response.json();
// check for error response
if (!response.ok) {
// get error message from body or default to response statusText
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
fetchedData.value = data;
})
.catch((error) => {
console.error("There was an error!", error);
return error;
});
return fetchedData;
}
And this is code from .vue file where I calling fetchData function:
<script setup>
import { fetchData } from "../../utils/universal-fetch";
import { ref, watch } from "vue";
import { useStore } from "../../stores/language.js";
import { useI18n } from "vue-i18n";
import AOS from "aos";
const store = useStore();
const { locale } = useI18n({ useScope: "global" });
const fetchedData = ref(fetchData("homeFirstSection", store.getLanguage));
AOS.init();
watch(
() => locale.value,
() => {
fetchedData.value = fetchData("homeFirstSection", store.getLanguage);
}
);
</script>
When page is created/refreshed, fetchData function fetch data from backend correctly. The problem which I'm trying to solve is that, when I change a locale, watcher automatically detects that, locale was changed and variable fetchedData should be updated based on choosen locale.
Problem
Thanks!
I found a problem. Here is code:
export function async fetchData(section, key) { // Added async
// GET request using fetch with error handling and headers
const headers = {
method: "GET",
headers: { "Content-Type": "application/json" },
};
let fetchedData = null;
await fetch( // Added await
"http://localhost:4000/api/" + section + "/?api-key=" + key,
headers
)
.then(async (response) => {
const data = await response.json();
// check for error response
if (!response.ok) {
// get error message from body or default to response statusText
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
fetchedData = data;
})
.catch((error) => {
console.error("There was an error!", error);
return error;
});
return fetchedData;
}
In my external .js file I was missing one more async await.
<script setup>
import { fetchData } from "../../utils/universal-fetch";
import { ref, watch } from "vue";
import { useStore } from "../../stores/language.js";
import { useI18n } from "vue-i18n";
import AOS from "aos";
const store = useStore();
const { locale } = useI18n({ useScope: "global" });
const fetchedData = ref(null);
fetchData("agreementsFirstSection", store.getLanguage).then(
(data) => (fetchedData.value = data)
); // Added .then
AOS.init();
watch(
() => locale.value,
() => {
fetchData("agreementsFirstSection", store.getLanguage).then(
(data) => (fetchedData.value = data)
); // Added .then instead of directly assign
}
);
</script>
And in .vue file I was missing .then insted of directly assigning value to variable. I added comments to code to compare changes before and after.
Problem solved
I am attaching all the function snippets below. I am using jest to run a unit test on this function but this needs to mock axios. I tried like this :
// TODO - mock axios class instance for skipped Test suites
describe("dateFilters()", () => {
beforeEach(() => {
jest.resetAllMocks();
});
it("Mock Fetch API for Date Options Response", async () => {
const mockFn = jest.fn();
setUpMockResponse(mockFn, mockFetchDateOptionsResponse);
const response = await dateFilters(Workload.WIN32);
expect(mockFn).toHaveBeenCalledTimes(1);
expect(response?.data).toEqual(mockFetchDateOptionsResponse);
});
});
The error I am getting is :
thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
It seems it is not mocking anything.
All the require function definitons are below:
export const dateFilters = async (platform) => {
const dates = await getKustoResponse({
queryName: platform.toLowerCase().concat("DateFilters"),
platform,
queryParams: {},
});
return dates;
};
export const getKustoResponse = async ({
queryName,
platform,
queryParams,
cluster = "Default",
}: QueryDetail) => {
const dbName = getClusterValue({ platform, cluster, key: "db" });
const url = getClusterValue({ platform, cluster, key: "kustoUrl" });
const postBody = {
db: dbName,
csl: queryParams
? substituteQueryParameters(queries[queryName], queryParams)
: queries[queryName],
};
const apiClient = ApiClient.getInstance();
const response = await apiClient.post(url, postBody, {
headers: {
...kustoApiRequestDefaultConfiguration.headers,
"x-ms-kql-queryName": queryName,
},
timeout: kustoApiRequestDefaultConfiguration.timeout,
});
return response;
};
import Axios, { AxiosInstance } from "axios";
import axiosRetry from "axios-retry";
export class ApiClient {
private static instance: AxiosInstance;
public static getInstance = (): AxiosInstance => {
if (!ApiClient.instance) {
ApiClient.createInstance();
}
return ApiClient.instance;
};
private constructor() {
ApiClient.getInstance();
}
protected static createInstance = () => {
const responseType = "json";
const client = Axios.create({
responseType,
});
axiosRetry(client, apiRetryConfiguration);
client.interceptors.request.use(requestInterceptor);
client.interceptors.response.use(responseInterceptor, errorInterceptor);
ApiClient.instance = client;
};
}
export const requestInterceptor = async (
request: AxiosRequestConfig
): Promise<AxiosRequestConfig> => {
const token = await getKustoToken();
request.headers = { ...request.headers, Authorization: `Bearer ${token}` };
return request;
};
There is no fetch call in your source code. Is it in the apiClient? If so, do this:
jest.spyOn(apiClient, 'post').mockImplementation();
expect(apiClient.post).toHaveBeenCalled();
I have multiple API calls with fairly lengthy, yet similar, response/error handling for each call.
What is the best non-repetitive ways to make multiple independent api calls that update state using fetch?
Copying and pasting 40+ instances of fetch doesn't seem right.
I want to avoid doing this ....
fetch(url,options)
.then((response) => {
// ...
return response.json
})
.then((data) => {
setState(data)
//...
})
.catch((err) => {
//Error logic here
})
Here's what I've done so far:
I made (found and modified) a useFetch hook...
useFetch.ts
//Only calls fetch() when .load() is called.
const useFetch = (path : string, HttpMethod : string, dependencies : any = [] , body : {} | undefined = undefined) => {
const history = useHistory()
const [response, setResponse] = useState<any>({});
const [error, setError] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
const [controller, setController] = useState(2)
const [isReady, setIsReady] = useState<any>(false)
const load = ():void => {
setError("")
//This prevents useEffect from triggering on declaration.
if (isReady) {
//Math.random() is just to get useEffect to trigger.
setController(Math.random())
}
}
const token = localStorage.getItem("token");
let requestOptions:any = {
method: HttpMethod,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "* always",
Authorization: "Token " + token,
},
};
if (body !== undefined) {
requestOptions["body"] = {
body: JSON.stringify(body)
}
}
const URI = BASE_URI + path
useEffect(() => {
const fetchData = async () => {
if (controller !== 2) {
setIsLoading(true);
try {
const res = await fetch(URI, requestOptions);
const json = await res.json();
if (json?.action == "ENFORCE_BILLING" ) {
history.push(BILLING_CREDENTIALS_PATH, { enforceBillingPopUp: true });
}
if (json?.action == "ENFORCE_SMS_CONFIRMATION") {
// Should we log user out, as well?
history.push(CONFIRMATION_CODE_PATH)
}
if (res.ok) {
setResponse(json);
setIsLoading(false)
} else {
setError(json)
setIsLoading(false)
}
} catch (err) {
setError(err);
// Error logic here...
}
}
}
};
fetchData()
setIsReady(true)
}, [controller, ...dependencies]);
return { response, setResponse ,error, isLoading, load, isReady };
};
Component.tsx
//Inside react functional component...
// Prepares to fetch data from back-end
const data1 = useFetch(PATH1, "GET");
const data2 = useFetch(PATH2, "GET");
const data3 = useFetch(PATH3, "GET");
useEffect(() => {
// Initial on load data fetch
// .load() fetches data
data1.load();
data2.load();
data3.load();
}, [activeReservations.isReady]);
// Sort data depending on sort selection
...
Is useFetch considered bad practice? What are the advantages of using Redux, instead?
Any help would be greatly appreciated. Thanks.