Setting a state in fetch call gives me undefined? - reactjs

Hi im trying to set a state in my fetch call, When I try to access the state it returns undefined. Im not sure why it does this can someone help?
var [articlearray, setArticle]= React.useState([]);
var options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({headline: props.headline})
};
fet(options)
function fet(options){
fetch('/headlines', options).then(response => response.json()).then(data =>{
var newsData = data.newsArray
setArticle(newsData)
})
}
console.log(articlearray[0]);

You could use useEffect to load all of your data from an API endpoint. The emtpy array [] on the useEffect means that it will run once, on the beginning of the lifecycle.
var [articlearray, setArticle] = React.useState([]);
const fetchData = async () => {
var options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
headline: props.headline
})
};
fetch('/headlines', options).then(response => response.json()).then(data => {
var newsData = data.newsArray;
setArticle(newsData);
console.log(articlearray[0]);
})
}
useEffect(() => {
fetchData();
}, []);

Related

converting custom react function to async

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

Why I need to refresh manually to fetch data api in react?

I make react app using react router v5, and axios as api instance. I fetch the data in AppRouter file.
Here is my approuter.tsx
const AppRouter = () => {
const dispatch = useAppDispatch();
const token = useAppSelector((state) => state.user.token);
const getUser = useCallback(async () => {
const { data } = await Services.getUser();
dispatch(userAction.setUser(data));
}, [dispatch]);
useEffect(() => {
const localStorage = new LocalStorageWorker();
const storageToken = localStorage.get('token');
dispatch(userAction.setToken(storageToken));
}, [dispatch]);
useEffect(() => {
if (token) {
getUser();
console.log('Worked');
}
}, [token, getUser]);
return (
...
)
}
Actually the function work properly, but I need to refresh the page manually to run these functions. How can I make the function run without refreshing the page?
Update:
The problem is because my axios create instance. I should use interceptors to keep the data fetching in useEffect.
My instance looks like this:
(before update)
const token = localStorage.get('token');
const createInstance = () => {
const instance = axios.create({
baseURL: BASE_URL,
headers: {
'content-type': 'application/json',
Accept: 'application/json',
},
});
instance.defaults.headers.common.Authorization = `Bearer ${token}`;
return instance;
};
(after update)
const createInstance = () => {
const instance = axios.create({
baseURL: BASE_URL,
headers: {
'content-type': 'application/json',
Accept: 'application/json',
},
});
instance.interceptors.request.use(
(config) => {
const token = window.localStorage.getItem('token');
if (token) {
return {
...config,
headers: { Authorization: `Bearer ${token}` },
};
}
return null;
},
(err) => Promise.reject(err)
);
return instance;
};
And now the data fetching is work properly. Thank you

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>
)
}

Call two fetch function with setState in between

I am trying to call two fetch APIs to store the information.
After first API call to cloudinary I get the URL back, which I want to store in state before hitting second API to store info in database. I am getting setAddOnData undefined error. While I try to make second API call , code functions properly for single API
const onSubmit = e => {
e.preventDefault();
console.log(fileInputRef.current.files[0]);
const myNewCroppedFile = fileInputRef.current.files[0];
console.log(myNewCroppedFile);
const formData = new FormData();
formData.append('file', myNewCroppedFile);
formData.append('upload_preset', 'xprl6rwq');
const options = {
method: 'POST',
body: formData
};
const addOnBody = JSON.stringify({ itemName, itemIconURL, itemPrice });
const config = {
headers: {
'Content-Type': 'application/JSON'
}
};
const option2 = {
method: 'POST',
body: addOnBody
};
return fetch(
'https://api.Cloudinary.com/v1_1/antilibrary/image/upload',
options
)
.then(res => res.json())
.then(res =>
setAddOnData({
...addOnData,
itemIconURL: res.secure_url
})
)
.then(fetch(`/api/v1/addOn`, option2, config))
.then(res => res.json());
};
const [addOnData, setAddOnData] = useState({
addOnCategory: '',
itemName: '',
itemPrice: '',
itemIconURL: '',
itemIconFileName: '',
step: 1
});
setState calls are asynchronous. When you run your second fetch call, the setAddOnData hasn't necessarily updated the addonData variable yet. You'd be best off moving the second fetch call to a useEffect which is dependent on the data returned from your first fetch call.
const addOnBody = JSON.stringify({ itemName, itemIconURL, itemPrice });
const config = {
headers: {
'Content-Type': 'application/JSON'
}
};
const option2 = {
method: 'POST',
body: addOnBody
};
const onSubmit = e => {
...
return fetch(
'https://api.Cloudinary.com/v1_1/antilibrary/image/upload',
options
)
.then(res => res.json())
.then(res =>
setAddOnData({
...addOnData,
itemIconURL: res.secure_url
})
)
};
useEffect( () => {
fetch(`/api/v1/addOn`, option2, config)
.then(res => res.json());
},[addOnData.itemIconURL])

Unable to get response using fetch in React

I am trying to call 3rd party API, to fetch some data. I am getting the response in Postman, but not getting expected response when I execute my code.
I tried in 2 ways. Both ways I am getting "Promise pending".What could be the reason??
//request.js
Method 1
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
return new Promise((resolve, reject) => {
setTimeout(() => resolve(
fetch(url, {
method: 'GET',
// mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
if (!res.ok) {
return Promise.reject(res.statusText);
}
console.log("hi", res.json());
return res.json();
})
.then(gifts => dispatch(searchGiftsSuccess(gifts)))
.catch(err => dispatch(searchGiftsError(err)))), 500)
});
}
Method 2:
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
fetch(url, {
method: 'GET',
// mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
if (!res.ok) {
return Promise.reject(res.statusText);
}
console.log('result', res.json());
return res.json();
})
.then(gifts => dispatch(searchGiftsSuccess(gifts)))
.catch(err => dispatch(searchGiftsError(err)));
};
//form.js
class Form extend React.Component{
onSubmit(values) {
const inputs = Object.assign({}, values);
return this.props.dispatch(callSearchGiftsAPI(inputs));
}
//Remaining code
}
Also please note that I have installed CORS plugin in Chrome, to allow the request.If I disable it and add mode:'no-cors' I am getting as 401 unauthorized.What else am I supposed to do?
What happens is that you are creating a new Promise and returning it, but you are not waiting for it to resolve. You can either use then of the new async/await syntax to get the correct result :
onSubmit = async values => {
const inputs = Object.assign({}, values);
return await this.props.dispatch(callSearchGiftsAPI(inputs));
}
The code above will work with your first method.
Since your second method does not return anything, you will never get your result, you need to return your fetch's result and apply the code I gave above :
return fetch(url, {
This worked.
I was trying to put console.log in the wrong place and hence was not able to see the response properly.
export const callSearchGiftsAPI = inputs => dispatch => {
dispatch(searchGifts());
let url = new URL(GIFT_SEARCH_API_URL),
params = {
apiKey: GIFT_SEARCH_API_KEY,
query: inputs.item,
country: 'us',
itemsPerPage: 3
};
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
console.log(url);
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `secret ${SECRET}`
}
})
.then(res => {
console.log('result');
return res.json();
})
.then(response => {
console.log(response); // changed
dispatch(searchGiftsSuccess(response.items));
})
.catch(err => dispatch(searchGiftsError(err)));

Resources