简体   繁体   中英

GET error 400 bad request on second axios api call

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)

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM