如何在点击react native时更改同一屏幕中的内容

9ceoxa92  于 2023-01-21  发布在  React
关注(0)|答案(2)|浏览(146)

我有一个主屏幕,其中有一个平面列表来显示图像和电影标题( Package 在一个盒子组件中),当点击该组件时会被定向到MovieDetail 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;

这是电影细节屏幕

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;

在主屏幕和电影细节屏幕上,有一个renderItem函数用于显示电影细节,当按下这两个函数时,将进入电影细节屏幕。

k97glaaz

k97glaaz1#

MovieDetail屏幕中,您不需要导航,因为您不想更改当前屏幕。要保持相同的逻辑并更新导航参数,请将

navigation.navigate('Detail Film', {
  data: item.id,
  title: item.title,
})

navigation.setParams({
  data: item.id,
  title: item.title,
})

请注意,您需要更新数据。我认为您可能需要添加一个componentDidUpdate函数来完成此操作。我现在不再熟悉它,因为我将使用useEffect以函数的方式完成此操作。

5n0oy7gb

5n0oy7gb2#

如果我没理解错你的问题的话,简单的解决办法应该是这样的。
1.将电影ID从主页传递到电影详细信息屏幕。

navigation.navigate('Detail Film', { movieId: 'xxxx1234'}

1.将此ID设置为MovieDetail屏幕中的默认状态。

this.setState({ movieId: this.props.route.params.movieId }

1.您可以在componentDidMount中获取电影细节。
1.您无需在MovieDetail屏幕中重新导航,当您单击某个电影时,只需设置新的movieId状态并检查componentDidUpdate中moveId的状态

componentDidUpdate(prevProps, prevState) {
 if(this.state.movieId !== prevState.movieId){ 
   // refetch movie details here 
 }
}

顺便说一句如果你使用reactnavigation当你在params中传递变量时要小心.更多信息

相关问题