skip to Main Content

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


  1. 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.

    Login or Signup to reply.
  2. If I understood your question correctly.
    The simple solution should be like this.

    1. Pass id of movie from Home to MovieDetail screen.
    navigation.navigate('Detail Film', { movieId: 'xxxx1234'} 
    
    1. Set this id to default state in MovieDetail screen.
    this.setState({ movieId: this.props.route.params.movieId }
    
    1. You can fetch movie detail in componentDidMount as you do.
    2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search