我是新手。我正在尝试使用 MoviesScreen 和 MovieDetailsScreen 构建两个屏幕的电影应用程序。 MoviesScreen 显示带有平面列表的电影列表,MovieDetailsScreen 显示电影信息,还使用平面列表显示该电影中的演员。 MoviesScreen 是 MoviesDetailsScreen 的父组件,当 MoviesDetailsScreen 导航回 MoviesScreen 时,按下任何电影都会导致崩溃。我认为这是一个平面列表问题,因为 MoviesDetailsScreen 有一个演员平面列表,并且由于数据是远程收集的,所以这两个平面列表无法真正调整。我该如何解决这个问题?这是我的 MoviesScreen:
function MoviesScreen({ route, navigation }) {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState();
const { moviesParam, queryString } = route.params || {};
const [movies, setMovies] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const flatListRef = useRef(null);
useLayoutEffect(() => {
setIsLoading(true);
if (moviesParam === "query" && queryString !== "") {
// execute the getItemsByQuery function with the queryString value
async function getItems() {
try {
const movies = await FetchMoviesByQuery(queryString);
setMovies(movies);
} catch (error) {
setError("Searching is not available at this time!");
} finally {
setIsLoading(false);
}
}
getItems();
} else {
setIsLoading(true);
}
}, [queryString, navigation]);
// Fetch movies when currentPage or moviesParam changes
useLayoutEffect(() => {
async function getMovies() {
let remainingUrl = "";
if (moviesParam == "trending") {
remainingUrl = "trending/movie/week?api_key=";
} else {
remainingUrl = `movie/${moviesParam}?api_key=`;
}
try {
const { movies, totalPages } = await FetchMovies(
remainingUrl,
currentPage
);
setMovies((prevMovies) => [...prevMovies, ...movies]);
setTotalPages(totalPages);
} catch (error) {
setError("Movies List is not available at this time!");
} finally {
setIsLoading(false);
}
}
if (
(moviesParam === "query" && queryString !== "") ||
currentPage > totalPages
) {
// do nothing
return;
}
getMovies();
}, [moviesParam, currentPage]);
function errorHandler() {
setError(null);
}
if (error && !isLoading)
return <ErrorOverlay message={error} onConfirm={errorHandler} />;
if (isLoading) return <LoadingOverlay />;
if (movies.length === 0)
return <EmptyListOverlay navigation={navigation} screenName="Movies Tab" />;
function renderMovies(itemData) {
function pressHandler() {
navigation.navigate("Movie Details", {
movieId: itemData.item.id,
});
}
return (
<>
<MovieList {...itemData.item} onPress={pressHandler} />
</>
);
}
return (
<>
<FlatList
ref={flatListRef}
data={movies}
keyExtractor={(item) => item.id}
renderItem={renderMovies}
horizontal={false}
numColumns={3}
onEndReached={() => {
if (currentPage < totalPages) {
setCurrentPage(currentPage + 1);
}
}}
onEndReachedThreshold={0.5}
/>
<ReloadButton
navigation={navigation}
screenName="Movies Tab"
flatListRef={flatListRef}
/>
</>
);
}"
电影细节屏幕:
function MovieDetailsScreen({ route, navigation }) {
const { movieId } = route.params;
let remainingUrl = `movie/${movieId}?api_key=`;
const [movie, setMovie] = useState([]);
const [actors, setActor] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [isLoadingActors, setIsLoadingActors] = useState(true);
const [error, setError] = useState();
const [isMovieLoaded, setIsMovieLoaded] = useState(false);
const flatListRef = useRef(null);
const memoizedMovieDetails = useMemo(() => {
return <MovieDetails {...movie} />;
}, [movie]);
useLayoutEffect(() => {
async function getMovie() {
setIsLoading(true);
try {
const movie = await FetchMovieDetails(remainingUrl);
setMovie(movie);
setIsMovieLoaded(true);
navigation.setOptions({
title: `${movie.title}`,
});
} catch (error) {
setError("Movie Details Are not Available");
}
setIsLoading(false);
}
getMovie();
}, [remainingUrl, movieId, navigation]);
useLayoutEffect(() => {
if (!isMovieLoaded) return;
setIsLoadingActors(true);
async function getActorInformation() {
try {
const actorDetails = await FetchActorsByMovie(movieId);
setActor(actorDetails);
} catch (error) {
setError("Star Casts are not available");
}
setIsLoadingActors(false);
}
getActorInformation();
return () => {
setActor([]); // <-- add cleanup function to clear the actors state
};
}, [movieId, isMovieLoaded]);
function errorHandler() {
setError(null);
}
if (error && !isLoading) {
return <ErrorOverlay message={error} onConfirm={errorHandler} />;
}
if (isLoading || isLoadingActors || !isMovieLoaded) {
return <LoadingOverlay />;
}
return (
<View style={styles.container}>
{isMovieLoaded && (
<MovieDetailsTop
movie={movie}
/>
)}
{isMovieLoaded && !isLoadingActors && (
<FlatList
ref={flatListRef}
data={actors}
windowSize={5}
initialNumToRender={3}
maxToRenderPerBatch={6}
removeClippedSubviews={true}
keyExtractor={(item) => item.id.toString()}
renderItem={(itemData) => (
<ActorList itemData={itemData} navigation={navigation} />
)}
horizontal={false}
numColumns={3}
ListHeaderComponent={<>{memoizedMovieDetails}</>}
/>
)}
<MinimizableText text={`Overview: ${movie.overview}`} />
</View>
);
}
export default MovieDetailsScreen;
我尝试设置多个加载条件,但没有一个有效。作为参考,我在 MovieDetailsScreen 中保留了加载条件,我也在 MoviesScreen 上尝试了它们,但它们并没有解决问题。还尝试使用 useEffect 而不是 useLayoutEffect,但没有解决问题。