converting custom react function to async - reactjs

I made this custom hook.
import axios from "axios";
import Cookies from "js-cookie";
import React from "react";
const useGetConferList= () => {
let token = JSON.parse(localStorage.getItem("AuthToken"));
const Idperson = JSON.parse(Cookies.get("user")).IdPerson;
const [response, setResponse] = React.useState();
const fetchConfer= (datePrensence, idInsurance, timePrensence) => {
axios({
method: "post",
url: `${process.env.REACT_APP_API_URL_API_GET_ERJASERVICE_LIST}`,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
data: JSON.stringify({
datePrensence,
idInsurance,
Idperson,
searchfield: "",
timePrensence: parseInt(timePrensence) * 60,
}),
})
.then((r) => {
setResponse(r.data.Data);
})
.catch(() => alert("NetworkError"));
};
return { fetchConfer, response };
};
export default useGetConferList;
as you can see I export the fetchConfer function. but I want to make it async. for example, calling the function and then doing something else like this:
fetchConfer(Date, Time, Id).then((r) => {
if (search !== "") {
window.sessionStorage.setItem(
"searchList",
JSON.stringify(
r.data
)
);
}
});
as you can see in non async situation, I can't use then.

You can try this
const fetchConfer = async (datePrensence, idInsurance, timePrensence) => {
try {
const response = await axios({
method: "post",
url: `${process.env.REACT_APP_API_URL_API_GET_ERJASERVICE_LIST}`,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
data: JSON.stringify({
datePrensence,
idInsurance,
Idperson,
searchfield: "",
timePrensence: parseInt(timePrensence) * 60,
}),
})
setResponse(response.data.Data);
// need to return data
return response.data.Data
} catch(error) {
alert("NetworkError")
}
};
use the function in another async function
const someAsyncFunc = async () => {
// try catch
const r = fetchConfer(Date, Time, Id)
if (search !== "") {
window.sessionStorage.setItem(
"searchList",
JSON.stringify(
r.data
)
);
}
...
or use it how you are currently using it
Hope it helps

Related

how to solve problem with oAuth Zoom in Nextjs?

I am trying to authenticate the user in order to get data to use to create or update meetings later. but it full of errors.
Here I am sending Post Requests in order to get the AccessToken and then get the UserData as props.
export async function getServerSideProps(res){
const oauth = async() => {
const zoomUserData = [];
const b = Buffer.from(process.env.ZOOM_API_KEY + ":" + process.env.ZOOM_API_SECRET);
const zoomRes = await fetch(`https://zoom.us/oauth/token?grant_type=authorization_code&code=${req.body.code}&redirect_uri=${process.env.ZOOM_REDIRECT_URL}`, {
method: "POST",
headers: {
Authorization: `Basic ${b.toString("base64")}`,
},
});
const zoomData = await zoomRes.json();
const zoomUserRes = await fetch("https://api.zoom.us/v2/users/me", {
method: "GET",
headers: {
Authorization: `Bearer ${zoomData.access_token}`,
},
});
const zoomUserData = await zoomUserRes.json();
/*
Encrypt and store below details to your database:
zoomUserData.email
zoomUserData.account_id
zoomData.access_token
zoomData.refresh_token
zoomData.expires_in // convert it to time by adding these seconds to current time
*/
}
return{
props:{zoomUserData}
}
}
and then i am passing the props to a page component like that :
export default function Meeting({zoomUserData}) {
const router = useRouter();
useEffect(() => {
if (router.query.code) {
fetch('/connectZoom',
{ method: 'POST',
headers: {
'ContType': 'application/json',
},
body: JSON.stringify({ code: router.query.code }),
}).then(() => {
console.log("success")
}).catch(() => {
console.log("No!")
});
}
}, [router.query.code]);
console.log(zoomUserData)
return (
<a href={`https://zoom.us/oauth/authorize?response_type=code&client_id=${process.env.ZOOM_API_KEY}&redirect_uri=${process.env.ZOOM_REDIRECT_URL}`}>
Connect Zoom
</a>
)
}

Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.How to fix

I am doing an online diary and get problems with fetching inside jsx component. I have 2 requests. First for fetching lessons and its returns dates and ids of lessons. And second that fetching marks in this lessons but second return [object Promise] but fetch is ok. So how I can get normal data(not a [object Promise]?
const [marks, setMarks] = useState([])
const [lessons, setLessons] = useState([])
const [loading, setLoading] = useState(true)
const getLessons = async(subjectID) => {
var res = await fetch("http://localhost:5002/graphql", {
method: "post",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.authToken
},
body: JSON.stringify({
query: `query adad {
getSubjectLessons(subject:${subjectID}){
id,
date
}}`,
}),
}).then(data => data.json())
setLessons(res.data.getSubjectLessons)
getAllMarks(res.data.getSubjectLessons);
console.log(res.data.getSubjectLessons)
}
const getMark = async(pupilID, lessonID) => {
var res = await fetch("http://localhost:5002/graphql", {
method: "post",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.authToken
},
body: JSON.stringify({
query: `query adad {
getPupilMarksByLesson(lesson: ${lessonID} , pupil:${pupilID}){
mark
}
}`,
}),
}).then(data => data.json())
if (res.data.getPupilMarksByLesson !== null) {
console.log(res.data.getPupilMarksByLesson.mark)
return res.data.getPupilMarksByLesson.mark
} else {
return res.data.getPupilMarksByLesson
}
}
const getAllMarks = (lessons) => {
return setMarks(lessons.map(el => {
return ( <th> {
getMark(p.pupilID, el.id)
} </th>)
}))
}
useEffect(() => {
getLessons(p.subjectID);
setLoading(false);
}, [])
You are using async/await and .then() improperly in some places. Try this way:
const [marks, setMarks] = useState([])
const [lessons, setLessons] = useState([])
const [loading, setLoading] = useState(true)
const getLessons = async(subjectID) => {
var res = await fetch("http://localhost:5002/graphql", {
method: "post",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.authToken
},
body: JSON.stringify({
query: `query adad {
getSubjectLessons(subject:${subjectID}){
id,
date
}}`,
}),
})
var data = await res.json()
setLessons(data.getSubjectLessons)
getAllMarks(data.getSubjectLessons);
console.log(data.getSubjectLessons)
}
const getMark = async(pupilID, lessonID) => {
var res = await fetch("http://localhost:5002/graphql", {
method: "post",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.authToken
},
body: JSON.stringify({
query: `query adad {
getPupilMarksByLesson(lesson: ${lessonID} , pupil:${pupilID}){
mark
}
}`,
}),
})
var data = await res.json()
if (data.getPupilMarksByLesson !== null) {
console.log(data.getPupilMarksByLesson.mark)
return data.getPupilMarksByLesson.mark
} else {
return data.getPupilMarksByLesson
}
}
const getAllMarks = (lessons) => {
return setMarks(lessons.map(el => {
return ( <th> {
getMark(p.pupilID, el.id)
} </th>)
}))
}
useEffect(() => {
getLessons(p.subjectID);
setLoading(false);
}, [])
if you are using async and await then dont use .then syntax try to do like this
const getLessons = async (subjectID) => {
const res = await fetch('http://localhost:5002/graphql', {
method: 'post',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + localStorage.authToken,
},
body: JSON.stringify({
query: ` query adad {
getSubjectLessons(subject:${subjectID}){
id,
date
}}`,
}),
});
const data = await res.json();
setLessons(data.getSubjectLessons);
getAllMarks(data.getSubjectLessons);
console.log(data.getSubjectLessons);
};
or simply you can use third party library like axios
install it with npm or yarn with following command npm i axios or yarn add axios
and try it like this
const getLessons = async (subjectID) => {
const data = {
query: `query adad {
getSubjectLessons(subject:${subjectID}){
id,
date
}}`,
};
const config = {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + localStorage.authToken,
};
const { data } = await axios.post(
'http://localhost:5002/graphql',
data,
config
);
setLessons(data.getSubjectLessons);
getAllMarks(data.getSubjectLessons);
console.log(data.getSubjectLessons);
};
or make sure that you are not passing object in jsx.

How to show data using react

you are currently using react to replicate Spotify.
You are currently developing a search function and have successfully received a response.
I want to show this on the screen.
How do I solve this? Please help me.
const onClick = () => {
const inputSearchData = sessionStorage.getItem('inputData');
const inputTypeData = sessionStorage.getItem('inputType');
// console.log(inputTypeData)
axios({
headers: {
"Authorization": `Bearer ${token}`,
"Accept": "application/json",
"Content-Type": "application/json",
},
method: 'GET',
url: 'https://api.spotify.com/v1/search',
params: {
q: inputSearchData,
type: inputTypeData,
},
}).then((res) => {
console.log(res);
}).catch(err => {
console.log(err);
})
}
when you get your response from your axios request you need to store it inside react state.
access this inside the return statement of the component.
That will be something like that :
const SomeComponent = () => {
const [response, setResponse] = useState();
const onClick = async () => {
const inputSearchData = sessionStorage.getItem("inputData");
const inputTypeData = sessionStorage.getItem("inputType");
await axios({
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/json",
"Content-Type": "application/json"
},
method: "GET",
url: "https://api.spotify.com/v1/search",
params: {
q: inputSearchData,
type: inputTypeData
}
})
.then((res) => {
setResponse(res);
})
.catch((err) => {
console.log(err);
});
};
return (
<div>
{/* Access your response state over here */}
{/* That will be something like that : */}
{response.map((item, index) => {
<div key={index}>
{item.somethingFromYourData}
</div>
})}
</div>
)
};

How do I create a Generic postToAPI(route, package2send) function in React?

In our project we are using the MERN stack
I want to create a generic function whose input is the path to any api endpoint in our server and the JSON package to POST to the server. I want it to return the JSON sent back from the server.
That way when we are developing our mobile app and web app, we can simply use this function for all of our api endpoint POSTs.
I'm very new to using React/React-Native so I'm sure that I'm not understanding some sort of key concept.
Here is what I have so far:
import React from 'react';
// returns whatever the respective apiEndpoint is suppose to return
function postToAPI(route, package2send)
{
async() =>
{
try
{
const payload = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: package2send
}
const res = await fetch(route, payload);
console.log(res);
const data = await response.json();
console.log(data);
return data;
}
catch(error)
{
console.error(error);
}
}
}
export default postToAPI;
Whenever I call this function from my Login.js after I
import { postToAPI } from './postToAPI'
I get this error: 'TypeError: Object(...) is not a function'
I'm sure there are multiple things wrong with this code, so if someone could steer me in the right direction, it would be greatly appreciated.
If you export the function as default, you must import without bracket like that.
import postToAPI from './postToAPI';
If you would like to write a generic API call class, I advise you this class which I wrote before.
import { BASE_URL } from "../config";
import { Actions } from "react-native-router-flux";
import { deleteUserInfo } from "./SessionHelper";
const API_URL = BASE_URL;
class ApiHelper {
private accessToken?: string;
constructor() {
this.accessToken = undefined;
}
setAccessToken = (accessToken: string) => {
this.accessToken = accessToken;
};
getAccessToken = () => {
return this.accessToken;
};
getRequest = async (endpoint: string) => {
try {
const response = await fetch(`${API_URL}${endpoint}`, {
method: "GET",
headers: {
"x-access-token": `${this.accessToken}`
}
});
const responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
};
postRequest = async (endpoint: string, body: any) => {
try {
const response = await fetch(`${API_URL}${endpoint}`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"x-access-token": `${this.accessToken}`
},
body: JSON.stringify(body)
});
const responseJson = await response.json();
const finalResponse = { data: responseJson, status: response.status };
if (response.status === 401) {
deleteUserInfo();
this.accessToken = undefined;
Actions.auth();
}
return finalResponse;
} catch (error) {
console.error(error);
return error;
}
};
patchRequest = async (endpoint: string, body: any) => {
try {
const response = await fetch(`${API_URL}/${endpoint}`, {
method: "PATCH",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"x-access-token": `${this.accessToken}`
},
body: JSON.stringify(body)
});
const responseJson = await response.json();
const finalResponse = { data: responseJson, status: response.status };
if (response.status === 401) {
deleteUserInfo();
this.accessToken = undefined;
Actions.auth();
}
return finalResponse;
} catch (error) {
console.error(error);
}
};
deleteRequest = async (endpoint: string, body: any) => {
try {
const response = await fetch(`${API_URL}/${endpoint}`, {
method: "DELETE",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"x-access-token": `${this.accessToken}`
},
body: JSON.stringify(body)
});
const responseJson = await response.json();
const finalResponse = { data: responseJson, status: response.status };
if (response.status === 401) {
deleteUserInfo();
this.accessToken = undefined;
Actions.auth();
}
return finalResponse;
} catch (error) {
console.error(error);
}
};
}
export const APIHelper = new ApiHelper();

How to make that was only one function fetchData?

I have a function apiFunction inside the useEffect, which make request to the server:
useEffect(() => {
async function fetchData(currentPage, searchInput ) {
try {
const res = await apiFunction ('api/categories', { method: 'GET'}, currentPage, searchInput);
setValue(prev => ({
...prev,
listCategory: res.data,
currentPage: res.page,
buttonsPagination: Math.ceil(res.total / res.perPage)
}));
} catch (e) {
console.error(e);
}
}
fetchData(value.currentPage, value.searchInput);
}, [value.currentPage, value.searchInput]);
Function apiFunction is in a separate file and looks like this:
export const apiFunction = async (url, args, valuePage) => {
const response = await fetch(`${apiUrl}${url}?page=${valuePage}&q=${valueFilter}`, {
...args,
headers: {
"Content-type": "application/json; charset=UTF-8 ",
"Accept": 'application/json',
...args.headers,
},
});
return response.json();
}
This function was created simply for convenience. But now I dont need this function. I need that code from apiFunction was inside function fetchData. That is, that the function apiFunctiondid not exist at all.
How to implement it?
You can simply replace the apiFunction with fetch call in your component like below
useEffect(() => {
async function fetchData(currentPage, searchInput) {
try {
const resJson = await fetch(`${apiUrl}api/categories?page=${currentPage}`, {
method: 'GET'
headers: {
"Content-type": "application/json; charset=UTF-8 ",
Accept: "application/json",
}
});
const res = await resJson.json();
setValue(prev => ({
...prev,
listCategory: res.data,
currentPage: res.page,
buttonsPagination: Math.ceil(res.total / res.perPage)
}));
} catch (e) {
console.error(e);
}
}
fetchData(value.currentPage, value.searchInput);
}, [value.currentPage, value.searchInput]);

Resources