I've been practicing react native for the past few days. And I'm trying to make a movie page application. My code works as it should be. But my problem is that it shows an error about a possible unhandled promise rejection. I know where the problem is rooting from, but I don't know how to fix it.
Here is where the problem is rooting from (Details.js):
import { isEmptyStatement } from '@babel/types';
import React, {useEffect, useState} from 'react';
import {Text} from 'react-native';
import {getMovie, getTv} from '../services/services';
const Detail = ({route, navigation}) => {
const movieId = route.params.movieDetail.id;
const [movieDetail, setMovieDetail] = useState([]);
const [movieTv, setMovieTv] = useState([]);
const [loaded, setLoaded] = useState(false);
const [success, setSuccess] = useState(false);
useEffect(() => {
getMovie(movieId).then(movieData => {
if(movieData == null) {
setLoaded(false);
}
else {
setMovieDetail(movieData);
setLoaded(true);
}
});
}, [movieId]);
useEffect(() => {
getTv(movieId).then(movieTv => {
if(movieTv == null) {
setLoaded(false);
}
else {
setMovieTv(movieTv);
setLoaded(true);
}
});
}, [movieId]);
if(movieDetail.title == null){
return (
<React.Fragment>
{loaded && <Text>{movieTv.name}</Text>}
</React.Fragment>
);
}
else {
return (
<React.Fragment>
{loaded && <Text>{movieDetail.title}</Text>}
</React.Fragment>
);
}
console.log(movieTv.success);
}
export default Detail;
And this is where they get the data (services.js):
import axios from 'axios';
const apiUrl = 'https://api.themoviedb.org/3';
const apiKey = 'api_key=31a7f8174b1e2c29744ec644af796973';
// Get Popular Movies
export const getPopularMovies = async () => {
const resp = await axios.get(`${apiUrl}/movie/popular?${apiKey}`,);
return resp.data.results;
};
// Get Upcoming Movies
export const getUpcomingMovies = async () => {
const resp = await axios.get(`${apiUrl}/movie/upcoming?${apiKey}`,);
return resp.data.results;
};
// Get Popular TV
export const getPopularTv = async () => {
const resp = await axios.get(`${apiUrl}/tv/popular?${apiKey}`,);
return resp.data.results;
};
export const getFamilyMovies = async () => {
const resp = await axios.get(`${apiUrl}/discover/movie?${apiKey}&with_genres=10751`,);
return resp.data.results;
};
export const getMovie = async id => {
const resp = await axios.get(`${apiUrl}/movie/${id}?${apiKey}`,);
return resp.data;
};
export const getTv = async id => {
const resp = await axios.get(`${apiUrl}/tv/${id}?${apiKey}`,);
return resp.data;
};
CodePudding user response:
You have used several async calls and working on the returned promises in your Details.js
class. But in each such case, you have only handled the success (promise resolve) path by providing only the then
callback.
For example, consider this
getTv(movieId).then(movieTv => {
if(movieTv == null) {
setLoaded(false);
}
else {
setMovieTv(movieTv);
setLoaded(true);
}
});
Here your application will work well, as long as the network call is successful and the backend returns a successful (e.g. 2xx) response. But if any error occurred, your application will crash as you haven't handled the error by handling the promise rejection.
So what you should do is add a catch
callback to each of these promises and handles the error scenario gracefully. You can do things like logging the error, set any flag to indicate the loading was failed, show an error on the UI etc.
getTv(movieId).then(movieTv => {
if(movieTv == null) {
setLoaded(false);
}
else {
setMovieTv(movieTv);
setLoaded(true);
}
}).catch(err => {
console.log(err);
setLoaded(false);
});