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.
CodePudding user response:
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
navigation.navigate('Detail Film', {
data: item.id,
title: item.title,
})
with
navigation.setParams({
data: item.id,
title: item.title,
})
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 with useEffect
.
CodePudding user response:
If I understood your question correctly. The simple solution should be like this.
- Pass id of movie from Home to MovieDetail screen.
navigation.navigate('Detail Film', { movieId: 'xxxx1234'}
- Set this id to default state in MovieDetail screen.
this.setState({ movieId: this.props.route.params.movieId }
- You can fetch movie detail in componentDidMount as you do.
- You no need to re-navigate in MovieDetail screen, when you click some movie just set new movieId state and checking the state of moveId in componentDidUpdate
componentDidUpdate(prevProps, prevState) { if(this.state.movieId !== prevState.movieId){ // refetch movie details here } }
by the way if you use reactnavigation be careful when you pass variable in params. more information