Reputation: 91
I'm trying to get data from an API using Axios. I have two API calls. The first call runs fine, and I get the data I expect. The second one, however, comes back with the 400 error bad request.
I've searched through multiple forums to try and find a solution, but I don't quite understand the code that I find.
const [player, setPlayer] = useState([]);
const [newPlayer, setNewPlayer] = useState([]);
const FindLoadout = async () => {
await axios.get(`http://api.paladins.com/paladinsapi.svc/getmatchidsbyqueueJson/${devId}/${generateSignature('getmatchidsbyqueue')}/${props.sess}/${moment.utc().format('YYYYMMDDHHmmss')}/428/${moment.utc().format('YYYYMMDD')}/-1,00`).then((response) => {
const playerData = response.data;
playerData.map((el) => {
player.push(el.Match)
})
console.log(player);
for(let i = 0; i < 50; i++) {
newPlayer.push(player[i]);
}
console.log(newPlayer);
}).catch((error) => {
console.log(error);
});
axios.get(`http://api.paladins.com/paladinsapi.svc/getmatchdetailsbatchJson/${devId}/${generateSignature('getmatchdetailsbatch')}/${props.sess}/${moment.utc().format('YYYYMMDDHHmmss')}/${newPlayer.join(",")}`).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
}
The error message is:
Error: Request failed with status code 400 at createError (createError.js:17) at settle (settle.js:19) at XMLHttpRequest.handleLoad (xhr.js:60)
Upvotes: 2
Views: 3610
Reputation: 306
I believe the problem is with how you are assigning values to player
and newPlayer
. Since you are using the useState
hook you are supposed to use setPlayer
and setNewPlayer
.
Could you tell me what's the value of newPlayer
before the second api call?
Maybe you could update it like this:
const FindLoadout = async () => {
await axios.get(`http://api.paladins.com/paladinsapi.svc/getmatchidsbyqueueJson/${devId}/${generateSignature('getmatchidsbyqueue')}/${props.sess}/${moment.utc().format('YYYYMMDDHHmmss')}/428/${moment.utc().format('YYYYMMDD')}/-1,00`).then((response) => {
const playerData = response.data;
//playerData.map((el) => {
// player.push(el.Match)
//})
setPlayer(playerData.map(el) => el.Match);
console.log(player);
//for(let i = 0; i < 50; i++) {
// newPlayer.push(player[i]);
//}
// I'm not sure how to update this assignment
console.log(newPlayer);
}).catch((error) => {
console.log(error);
});
axios.get(`http://api.paladins.com/paladinsapi.svc/getmatchdetailsbatchJson/${devId}/${generateSignature('getmatchdetailsbatch')}/${props.sess}/${moment.utc().format('YYYYMMDDHHmmss')}/${newPlayer.join(",")}`).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
}
About updating newPlayer
: since states are updated asynchronously, by the time you try to update newPlayer
using the values in player
, player
has nothing in it.
Try to make the request with some hardcoded values to see if the problem is with the api requests or with the values in your variables.
Upvotes: 0
Reputation: 1413
Firstly you are mixing async and traditional promises
[EDIT: you are also mutating state directly instead of using setState]
[EDIT2: setting state is not immediate therefor a console.log of state (and the axios get request relying on the state value) directly after a setState will not usually log the value you anticipate and therefore should be included inside the callback function passed to setState -or- utilize useEffect when the state does update]
[EDIT3: build new state outside of loop then setState after]
const [player, setPlayer] = useState([]);
const [newPlayer, setNewPlayer] = useState([]);
const FindLoadout = async () => {
useEffect(()=>{
if (!player.length) return
const newState = [...newPlayer]
for(let i = 0; i < 50; i++) {
newState.push(player[i]);
}
setNewPlayer(newState)
}, [player]);
useEffect(() => {
if (!newPlayer.length) return
axios
.get(`http://api.paladins.com/paladinsapi.svc/getmatchdetailsbatchJson/${devId}/${generateSignature('getmatchdetailsbatch')}/${props.sess}/${moment.utc().format('YYYYMMDDHHmmss')}/${newPlayer.join(",")}`)
.then((gameData)=>{
console.log(gameData)
}).catch((error)=>{
console.error(error)
})
}, [newPlayer]);
try {
const playerData= await axios.get(`http://api.paladins.com/paladinsapi.svc/getmatchidsbyqueueJson/${devId}/${generateSignature('getmatchidsbyqueue')}/${props.sess}/${moment.utc().format('YYYYMMDDHHmmss')}/428/${moment.utc().format('YYYYMMDD')}/-1,00`)
const newState = [...player]
playerData.map((el) => newState.push(el.Match))
setPlayer(newState)
}catch(error) {
console.error(error);
}
}
If you want to stick with asyc for the second useEffect you can also use a callback instead: https://dev.to/n1ru4l/homebrew-react-hooks-useasynceffect-or-how-to-handle-async-operations-with-useeffect-1fa8
useEffect(() => {
if (!newPlayer.length) return
const myCallback = async ()=>{
try{
const gameData = await axios.get(`http://api.paladins.com/paladinsapi.svc/getmatchdetailsbatchJson/${devId}/${generateSignature('getmatchdetailsbatch')}/${props.sess}/${moment.utc().format('YYYYMMDDHHmmss')}/${newPlayer.join(",")}`)
console.log(gameData)
}catch(error){
console.error(error)
}
}
myCallback()
}, [newPlayer]);
If that doesn't fix the issue:
The 400 Bad Request error is an HTTP status code that means that the request you sent to the website server was somehow incorrect or corrupted and the server couldn't understand it.
ie: Your URL is incorrect for the API call I would double check that the "generateSignature" function is returning the proper value. If that is the case I would check to make sure that newPlayer.join(",") is returning the proper value.
Upvotes: 0
Reputation: 759
I don't know if it will exactly address your problem, but when using async
/ await
for data fetching, a common practice is to do it more like this :
const FindLoadout = async () => {
const playerData= await axios
.get(`http://api.paladins.com/player/154`)
.then(response => response.data);
const gameData= await axios
.get(`http://api.paladins.com/game/788`)
.then(response => response.data);
return {player: playerData, game: gamedata}
}
That is to say, you assign the data fetched by your API calls to variables, and then return the data that you need from them (after whatever manipulation you deem necessary).
The ability to write asynchronous code in that kind of synchronous syntax is one of the most appealing trait of async
/ await
.
I suspect the errors you get are because you second call does not have the await
keyword before it is fired.
EDIT : also, as other have remarked, you are definitely going to encounter issues with your incorrect use of hooks, but this is not the scope of the question.
Upvotes: 2