I have a Home Screen in which there is a FlatList to display images and movie titles (wrapped in a box component), when the component is clicked it will be directed to MovieDetail Screen. In movie detail there are similar movie section, this similar movie uses the same way to display movies as on the homescreen, when I press one of the movies in the movie recommendation section, the contents of the movie detail screen do not change according to the movie I pressed, how do I make it so that when I press one of the movies in the similar movie section (on MovieDetail) it will change the contents of the MovieDetail Screen?
This my Home Screen
class Home extends Component {
constructor(props) {
super(props);
this.state = {
dataCSoon: [],
isContentLoading: false
isFetching: false,
};
}
getComingSoon = () => {
fetch(
'https://api.themoviedb.org/3/movie/upcoming?api_key=<The API Key Here>'
)
.then((response) => response.json())
.then((json) =>
this.setState({
dataCSoon: json.results,
})
)
.catch((error) => console.error(error))
.finally(() =>
this.setState({
isContentLoading: false,
isFetching: false,
})
);
};
componentDidMount = () => {
this.getComingSoon();
};
renderItem = ({ item }) => {
const { navigation } = this.props;
return (
<>
<Pressable
onPress={() =>
navigation.navigate('Detail Film', {
data: item.id,
title: item.title,
})
}>
<Box alignItems="center">
<Box
maxW="150"
h="260"
rounded="lg"
overflow="hidden"
borderWidth="1"
borderColor="coolGray.600"
backgroundColor="gray.700"
shadow="2"
m="2">
<Box>
<AspectRatio w="100%" ratio={16 / 9}>
<Image
source={{
uri: 'https://image.tmdb.org/t/p/w500/' + item.poster_path,
}}
alt="image"
h="200"
w="100%"
/>
</AspectRatio>
<Center
backgroundColor="rgba(52, 52, 52, 0Bu.7)"
position="absolute"
mt="176"
h="6"
w="20"
roundedTopRight="10"
roundedBottomRight="10">
<HStack>
<Icon
size="5"
color="#FF8700"
as={<Ionicons name="star-outline" />}
/>
<Text color="#FF8700" fontWeight="700" fontSize="14" ml="2">
{item.vote_average}
</Text>
</HStack>
</Center>
</Box>
<Stack p="4" space={3} mt="110">
<Stack space={2}>
<Heading fontSize="15" ml="-1" noOfLine="3" color="#fff">
{item.title}
</Heading>
</Stack>
</Stack>
</Box>
</Box>
</Pressable>
</>
);
};
render() {
const {
dataCSoon
} = this.state;
const { navigation } = this.props;
return (
<ScrollView>
<Box bgColor="#242A32" h="100%" pl="5" mb="5">
<Text color="#FFFFFF" mt="10" fontWeight="bold" fontSize="20">
Welcome
</Text>
<Text color="#FFFFFF" fontWeight="semibold" fontSize="15">
Choose Movie To View
</Text>
<View justifyContent="center">
<HStack my="4" space={145} w="100%" mt="5">
<Text color="#ffffff" fontSize="18">
Coming Soon
</Text>
<Pressable
onPress={() =>
navigation.navigate('More', { data: dataCSoon })
}>
<Text color="#0296E5" fontSize="15" mr="8" fontWeight="bold">
See More
</Text>
</Pressable>
</HStack>
<FlatList
mt="-2"
horizontal
data={ dataCSoon.slice(0, 4)}
keyExtractor={(item) => item.id}
renderItem={this.renderItem}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
/>
</View>
</Box>
</ScrollView>
);
}
}
export default Home;
This is MovieDetail Screen
class MovieDetail extends Component {
constructor(props) {
super(props);
this.state = {
dataId: this.props.route.params.data,
content: [],
contentGenre: [],
similar: [],
isContentLoading: true,
};
}
getContent = (movie_id) => {
fetch(
`https://api.themoviedb.org/3/movie/${movie_id}?api_key=<The API Key>`
)
.then((response) => response.json())
.then((json) =>
this.setState({
content: json,
})
)
.catch((error) => console.error(error))
.finally(() =>
this.setState({
isContentLoading: false,
isFetching: false,
})
);
};
getDetails = (movie_id) => {
fetch(
`https://api.themoviedb.org/3/movie/${movie_id}?api_key=<The API Key>`
)
.then((response) => response.json())
.then((json) =>
this.setState({
contentGenre: json.genres[0].name,
activeContent: json.id,
})
)
.then(() => this.fetchContent(this.state.activeContent))
.catch((error) => console.error(error))
.finally(() =>
this.setState({
isCategoriesLoading: false,
})
);
};
getSimilar = (movie_id) => {
fetch(
`https://api.themoviedb.org/3/movie/${movie_id}/similar?api_key=<The API Key>`
)
.then((response) => response.json())
.then((json) => this.setState({ similar: json.results }))
.catch((error) => console.error(error))
.finally(() =>
this.setState({
isContentLoading: false,
isFetching: false,
})
);
};
componentDidMount = () => {
const { dataId } = this.state;
this.getContent(dataId);
this.getDetails(dataId);
this.getSimilar(dataId);
};
renderItem = ({ item }) => {
const { navigation } = this.props;
return (
<>
<Pressable
onPress={() =>
navigation.navigate('Detail Film', {
data: item.id,
title: item.title,
})
}>
<Box alignItems="center">
<Box
maxW="150"
h="260"
rounded="lg"
overflow="hidden"
borderWidth="1"
borderColor="coolGray.600"
backgroundColor="gray.700"
shadow="2"
m="2">
<Box>
<AspectRatio w="100%" ratio={16 / 9}>
<Image
source={{
uri:
'https://image.tmdb.org/t/p/w500/' + item.poster_path,
}}
alt="image"
h="200"
w="100%"
/>
</AspectRatio>
<Center
backgroundColor="rgba(52, 52, 52, 0.7)"
position="absolute"
mt="176"
h="6"
w="20"
roundedTopRight="10"
roundedBottomRight="10">
<HStack>
<Icon
size="5"
color="#FF8700"
as={<Ionicons name="star-outline" />}
/>
<Text color="#FF8700" fontWeight="700" fontSize="14" ml="2">
{item.vote_average.toFixed(1)}
</Text>
</HStack>
</Center>
</Box>
<Stack p="4" space={3} mt="110">
<Stack space={2}>
<Heading fontSize="15" ml="-1" noOfLine="3" color="#fff">
{item.title}
</Heading>
</Stack>
</Stack>
</Box>
</Box>
</Pressable>
</>
);
};
render() {
const {
contentGenre,
content,
isContentLoading
similar,
} = this.state;
return isContentLoading ? (
<Spinner color="indigo.500" size="lg" mt="100%" />
) : (
<ScrollView h="100%">
<Box bgColor="#242A32" h="100%" pb="50">
<Image
source={{
uri: 'https://image.tmdb.org/t/p/w500/' + content.backdrop_path,
}}
w="100%"
h="250"
resizeMode="contain"
opacity="0.6"
borderBottomLeftRadius="20"
borderBottomRightRadius="20"
/>
<Image
source={{
uri: 'https://image.tmdb.org/t/p/w500/' + content.poster_path,
}}
w="30%"
h="150"
ml="5"
mt="-25%"
resizeMode="contain"
rounded="25"
/>
<View flexDirection="column" ml="4" mr="4">
<Text
color="#ffffff"
fontSize="18"
fontWeight="bold"
ml="38%"
mt="-17%"
w="60%"
noOfLine="2">
{content.title}
</Text>
<HStack mt="10" justifyContent="center">
<Text color="#ffffff" fontSize="14">
{content.id}
</Text>
<Divider
bg="#3A3F47"
thickness="3"
mx="2"
orientation="vertical"
/>
<Text color="#fff" fontSize="16" mt="4">
Similar
</Text>
<Divider
bg="#3A3F4F"
thickness="3"
w="20%"
orientation="horizontal"
/>
<FlatList
mt="2"
horizontal
data={similar}
keyExtractor={(item) => item.id}
renderItem={this.renderItem}
/>
</VStack>
</View>
</Box>
</ScrollView>
);
}
}
export default MovieDetail;
On the Home screen and MovieDetail Screen there is a renderItem function to display movie details, when pressed both will lead to the MovieDetail Screen.
2
Answers
In the
MovieDetail
Screen, you don’t need to navigate because you don’t want to change the current screen.To keep the same logic and update the navigation parameters, replace
with
Be aware that you will need to update the data. I think you may need to add a
componentDidUpdate
function to do so. I’m no longer familiar with it now, as I would do it in a functional way withuseEffect
.If I understood your question correctly.
The simple solution should be like this.
by the way if you use reactnavigation be careful when you pass variable in params.
more information