I have two async
functions which reach out to API endpoints (Serverless Framework) - one gets and returns a token, the other gets and returns data using the token.
I'm testing these by using simple buttons, where onClick
calls the functions to pull the token and the data, respectively. Click one button to get the token, which is saved to state. Then, once I see the token has been received, I click the other button to get the data. This works without any issues at all.
The problem is when I try calling them sequentially from the React app. I need to call these back-to-back when the user submits a request. I can't seem to make the code wait for the token to arrive before trying to pull the data.
The functions being called in the onClick
method of the button:
const tokenBtnOnClick = () =>
{
const response = getToken().then(x => {
setToken(x.data.response.token)
})
}
const dataBtnOnClick = () =>
{
const response = getData(token, param1, param2, param3).then(x => {
setData(x.data.response)
})
}
Async
functions:
export async function getToken()
{
const apiUrl = `${BASE_URL}/handler/getToken`
const axios = require('axios').default
let response
try
{
response = await axios.get(apiUrl)
}
catch (e)
{
console.log(e)
}
if (response)
{
return response
}
else
{
return ''
}
}
export async function getData(token, param1, param2, param3)
{
const apiUrl = `${BASE_URL}/handler/getData?token=${token}¶m1=${param1}¶m2=${param2}¶m3=${param3}`
const axios = require('axios').default
let response
try
{
response = await axios.post(apiUrl)
}
catch (e)
{
console.log(e)
}
if (response)
{
return response
}
else
{
return ''
}
}
I've tried calling this getBoth()
function in a single button's onClick
:
async function getBoth()
{
const tokenResponse = await tokenBtnOnClick().then(x => setToken(x.data.response.token))
const dataResponse = await dataBtnOnClick().then(x => setData(x.data.response))
}
But even though it's an async
function that uses await
on both lines, I always get the same TypeError
because dataBtnOnClick
is called immediately, without actually waiting for the token to come in. When I run this code, tokenBtnOnClick
is called, the app crashes due to a TypeError
, and then the token comes in and is logged and saved to state.
I've also tried this: (where getData
is exactly as above, but now accepts token
as a paramter rather than using the state variable)
async function getBoth()
{
const response = await getToken().then(x => getData(x.data.response.token))
}
index.js?bee7:59 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'then')
How do I get this to actually wait for the token to come in before trying to pull the data?
CodePudding user response:
You are calling setToken
and expection token
to be updated immediately, but setToken
will be asynchronously applied.
Can you useEffect
to solve your problem?
useEffect(() => {
getData(token, param1, param2, param3).then(x => {
setData(x.data.response)
})
}, [token])
CodePudding user response:
Try this
const tokenBtnOnClick = () =>{
setToken(getToken())
}
const dataBtnOnClick = () =>{
setData(getData(token, param1, param2, param3))
}
and
const axios = require('axios').default
export async function getToken()
let apiUrl = `${BASE_URL}/handler/getToken`
{
let response = await axios.get(apiUrl)
return response.data.token;
//i don't know exactly what the api returns so it may be diferent
}
export async function getData(token, param1, param2, param3)
{
let apiUrl = `${BASE_URL}/handler/getData? token=${token}¶m1=${param1}¶m2=${param2}¶m3=${param3}`
let response = await axios.post(apiUrl)
return response.data.response;
}
and in your getBoth() just call them because the functions are asynchronous the code will only move forward after them are finished
getBoth(){
setToken(getToken())
setData(getData(token, param1, param2, param3))
}