What if axios call in getServerSideProps() failed? How to repeat - javascript

I'm trying to pre render page using getServerSideProps in Next.js and everything works perfectly.
But what if the axios call failed due to server issue or Network error?
How can I repeat the call?
Here's my code:
export async function getServerSideProps() {
let ImagesList = {};
await axios
.get("https://www.*****.com/api/home")
.then((response) => {
if (response.data) {
ImagesList = response.data
}
})
.catch((err) => { });
return {
props: {
ImagesList,
}
}
}

you can try to wrap your axios call inside a while loop,
let result = false;
while(!result) {
await axios
.get("https://www.*****.com/api/home")
.then((response) => {
result = true
if (response.data) {
ImagesList = response.data
}
})
.catch((err) => { });
}

Related

Axios put return undefined [React JS + Axios]

Hi all im doing an axios put to update my data. However im getting an undefined response. Thank you in advance
function that call the Axios:
export function exUpdateMovie(movie) {
Axios.put(baseURL + "/api/update", {
movieName: movie.movieName,
movieReview: movie.movieReview,
id: movie.id,
})
.then((response) => {
// console.log(response);
return response;
})
.catch((e) => {
console.log(e);
return e;
});
}
function in app.js that calls the exUpdateMovie(movie) function:
const handleUpdateMovie = (movie) => {
console.log("UpdateMovie Passed!");
try {
const res = exUpdateMovie(movie);
alert(res?.data);
} catch (error) {
console.log(error);
}
};
Output when I alert my response is:
undefined
SETTLE:
need to add async and await at the handleUpdateMovie
need to return the Axios by doing return Axios.put()
Cheers mate for helping me. Thanks alot
Yes because your api call is returning a promise where you need to wait until the promise execution completes so make your function async and wrap the API call with await.
export async function exUpdateMovie(movie) {
const result = await Axios.put(baseURL + "/api/update", {
movieName: movie.movieName,
movieReview: movie.movieReview,
id: movie.id,
})
return result
}
const handleUpdateMovie = async (movie) => {
console.log("UpdateMovie Passed!");
try {
const res = await exUpdateMovie(movie);
alert(res?.data);
} catch (error) {
console.log(error);
}
};
Because exUpdateMovie doesn't return anything. Return the Promise:
export function exUpdateMovie(movie) {
return Axios.put(/* all your Axios code */);
}
Then when consuming the result, treat it as a Promise:
exUpdateMovie(movie).then(res => {
alert(res?.data);
});

I had 3 APIs need to called one after one

I create reactjs app when user ask for login I send three request
getToken();
createLogWithToken();
createRequestwithLog();
every function depend on the pervious one
here is my code
getToken = async (){
axios.post('getToken')
.then(response => {
this.setState({ token: response.data.token });
})
}
createLogWithToken = async (){
axios.post('createLogWithToken',{token:this.state.token})
.then(response => {
this.setState({ log_id: response.data.log_id });
})
}
createRequestwithLog = async (){
axios.post('createRequestwithLog',{token:this.state.token, log_id: this.state.log_id})
.then(response => {
this.setState({ request_id: response.data.request_id });
})
}
onPress = async () =>{
await this.getToken();
await this.createLogWithToken();
await this.createRequestwithLog();
}
I got error on the second commands as the required parameters is null
How can I call then and await till the the setstate done
Edit >>
I changed my code to be
getToken = async (){
await axios.post('getToken')
.then(response => {
this.setState({ token: response.data.token });
return (response.data.token);
})
}
createLogWithToken = async (token){
await axios.post('createLogWithToken',{token})
.then(response => {
this.setState({ log_id: response.data.log_id });
return response.data.log_id;
})
}
createRequestwithLog = async (token, log_id){
await axios.post('createRequestwithLog',{token, log_id})
.then(response => {
this.setState({ request_id: response.data.request_id });
return response.data.request_id;
})
}
onPress = async () =>{
let token = await this.getToken();
let log = await this.createLogWithToken(token);
let request = await this.createRequestwithLog(token,log);
}
but I still get error that token undefine
Several things:
The functions you are awaiting aren't "awaitable". You need to return a promise.
You can just await your axios calls directly like this const token = await axios.post...
setState isn't synchronous. You don't know if it's defined by the time you call the next endpoint. You should just set them in normal variables. If you also need them as state, you can do that too, but it doesn't look necessary
See How to structure nested Promises
fetch(url)
.then(function(response) {
return response.json()
})
.then(function(data) {
// do stuff with `data`, call second `fetch`
return fetch(data.anotherUrl)
})
.then(function(response) {
return response.json();
})
.then(function(data) {
// do stuff with `data`
})
.catch(function(error) {
console.log('Requestfailed', error)
});
getToken = async () {
const token = (await axios.post('getToken')).data.token;
this.setState({ token });
return token;
}
createLogWithToken = async (token) {
const logId = (await axios.post('createLogWithToken',{ token })).data.log_id;
this.setState({ log_id: logId });
return logId;
}
createRequestwithLog = async (token, logId) {
const requestId = (await axios.post('createRequestwithLog',{ token, log_id: logId })).data.request_id;
this.setState({ request_id: requestId});
}
onPress = async () => {
const token = await this.getToken();
const logId = await this.createLogWithToken(token);
this.createRequestwithLog(token, logId);
}

Is this the correct way to handle error when calling multi dispatch on a screen?

I am making multiple dispatch call in the homepage
Its was something like this.
useEffect(() => {
async function getStorageData() {
setLoading(true);
try {
await dispatch(fetchProductA());
await dispatch(fetchProductB());
await dispatch(fetchProductC());
await dispatch(fetchProductD());
await dispatch(fetchProductE());
} catch (err) {
console.log(err);
} finally {
setLoading(false);
}
}
getStorageData();
}, []);
The problem is that when calling the these api. I got an error when productC.
So I made a dispatch call.
I try throwing an error but that not work because when I throw an error in productC the remaining product D and E will not be called because throw end the dispatch calling
Here is my api call.
export const fetchProductC = () => dispatch => {
return axios
.get('productsapi/fetchProductC', {
headers: {
'Content-Type': 'application/json',
},
})
.then(res => {
dispatch({
type: FETCH_NEW_PRODUCTS,
payload: res.data[0]
});
})
.catch(err => {
dispatch({
type: EMPTY_NEW_PRODUCTS,
});
console.log('fetching new product error');
//throw err;
});
};
Here is the reducer
case FETCH_NEW_PRODUCTS:
return {
...state,
listC: action.payload,
};
case EMPTY_NEW_PRODUCTS:
return {
...state,
listC: [],
};
Your code after ProductC can't run because it is skipped via catch.
You can write your code like below.
await dispatch(fetchProductA()).catch(handleErr);
await dispatch(fetchProductB()).catch(handleErr);
await dispatch(fetchProductC()).catch(handleErr);
await dispatch(fetchProductD()).catch(handleErr);
await dispatch(fetchProductE()).catch(handleErr);
You should never await a dispatch in the component. Read tutorials and refactor your data flow: Redux Async Data Flow, Async Logic and Data Fetching
Redux recommends you to use thunk to do this:
// fetchTodoById is the "thunk action creator"
export function fetchTodoById(todoId) {
// fetchTodoByIdThunk is the "thunk function"
return async function fetchTodosThunk(dispatch, getState) {
// dispatch an action to set a loading state
dispatch(/*...*/)
const response = await client.get(`/fakeApi/todo/${todoId}`)
// use your response and set a success state here
dispatch(todosLoaded(response.todos))
}
}
// Your component
function TodoComponent({ todoId }) {
const dispatch = useDispatch()
const { data, state } = useSelector(/* your selector */)
const onFetchClicked = () => {
// Calls the thunk action creator, and passes the thunk function to dispatch
dispatch(fetchTodoById(todoId))
}
}

Struggling with promises and async functions in React

I'm working on a React project where I have a function that fetches paginated data recursively. This function is defined in another function, where I activate the loading screen with showLoading() at the start, where I'm calling the fetching data function in the body and deactivate the loading screen with hideLoading() at the end. The function:
const fetchPlaylist = (playlistId) => {
showLoading()
const getPlaylistDataRecursively = (url) => {
fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
.then(response => response.json())
.then(data => {
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
getPlaylistDataRecursively(next_url)
}
})
}
getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
hideLoading()
}
I believe I can attach a promise to the getPlaylistDataRecursively call with the then keyword but I'm getting a TypeError: Cannot read property 'then' of undefined. Probably because getPlaylistDataRecursively doesn't return anything. How do I make sure that hideLoading is called after getPlaylistDataRecursively is done?
You always need to return a promise.
const fetchPlaylist = (playlistId) => {
showLoading()
const getPlaylistDataRecursively = (url) => {
return fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
.then(response => response.json())
.then(data => {
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
return getPlaylistDataRecursively(next_url)
}
})
}
return getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
.then(() => hideLoading());
}
Or, using async/await:
const fetchPlaylist = async (playlistId) => {
showLoading()
const getPlaylistDataRecursively = async (url) => {
const response = await fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
const data = response.json()
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
await getPlaylistDataRecursively(next_url)
}
}
await getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
hideLoading()
}

Return Data from Axios

I am trying to return the response from an axios API call. I don't quite get what a promise is and all the tutorials/information I find they only log the response, I want to return it.
Here is what I have, but when I call getPokemon it's undefined.
const axios = require('axios');
const getPokemon = () => {
axios.get('https://pokeapi.co/api/v2/pokemon/')
.then(function (response) {
console.log("Response:", response.data.results);
return response.data.results;
})
.catch(function (error) {
return null;
});
}
export {getPokemon};
If this is a React app then you want to do your Axios call in componentDidMount. Axios automatically returns a promise.
class Example extends Component {
constructor(props) {
super(props);
this.state = {
data: ""
};
}
componentDidMount() {
axios
.get("https://pokeapi.co/api/v2/pokemon/")
.then(res => {
console.log(res);
this.setState({
data: res.data.results
});
})
.catch(err => {
console.log(err);
});
}
render() {
let pokemon = this.state.data;
let display = Object.values(pokemon).map((item, key) => {
return (
<div>
<p>{item.name}</p>
<p>{item.url}</p>
</div>
);
});
return (
<div>{display}</div>
);
}
}
export default Example;
Doing it like this will send the Axios request after the React app has loaded and set the JSON data in the component state. You should be able to access the JSON data via this.state.data.
Check out this Codepen example with working API call.
Well, first of all, I suggest you read about promises.
a good method for achieving what you need is by using async/await syntax check out the following code:
const axios = require('axios');
const getPokemon = async () => {
try{
let res = await axios.get('https://pokeapi.co/api/v2/pokemon/');
return res.data.results;
}
catch(error){
return null //that's what you did in your code.
}
}
export {getPokemon};
Remove ".result"
const axios = require("axios");
const getPokemon = async () => {
try {
let res = await axios.get("https://jsonplaceholder.typicode.com/users");
return res.data; **here remove his .result**
} catch (error) {
return null; //that's what you did in your code.
}
};
export default getPokemon;
In index.js or any page call it:
import getPokemon from "./GetPokimon";
const xyz = async () => {
const data = await getPokemon();
alert(JSON.stringify(data));//u will see the data here
}
xyz(); //calling getPokemon()

Categories

Resources