You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用handleFavoritePress切换CardFeirasPopulares的Image图片源?

图片源切换与收藏状态切换实现方案

一、通用方法:通过函数切换<Image />组件的图片源

要实现图片源切换,核心是利用React的状态管理(useState)——直接修改变量不会触发组件重渲染,只有状态更新才会让组件重新渲染,从而更新Image的source属性。

实现步骤:

  1. 导入useState钩子
  2. 定义状态变量保存当前图片源
  3. 编写切换函数,在函数中通过setState更新状态
  4. 将Image的source绑定到状态变量

示例代码:

import { useState } from 'react';
import { Image, TouchableOpacity } from 'react-native';

const ExampleComponent = () => {
  // 初始化状态为默认图片
  const [imageSource, setImageSource] = useState(icons.favorite);

  const toggleImage = () => {
    // 切换状态:当前是未收藏图标则切换为已收藏,反之亦然
    setImageSource(prev => prev === icons.favorite ? icons.favoritechecked : icons.favorite);
  };

  return (
    <TouchableOpacity onPress={toggleImage}>
      <Image source={imageSource} style={{ width: 24, height: 24 }} />
    </TouchableOpacity>
  );
};

二、针对你的React Native项目:实现收藏状态独立切换

你的代码存在两个核心问题:未用useState管理状态(直接赋值不会触发重渲染)、所有列表项共用同一状态(点击一个会同步所有卡片)。以下是修改后的完整代码:

1. 修改FeirasPopulares组件

为每个列表项单独管理收藏状态,用数组存储每个item的收藏状态:

import { useState } from 'react';
import {View, FlatList, Text, TouchableOpacity, StyleSheet} from 'react-native'
import CardFeirasPopulares from '../../common/cards/popular/CardFeirasPopulares'
import { useRouter } from "expo-router";
import { icons } from '../../../constants';

const FeirasPopulares = () => {
  // 初始化收藏状态数组,所有item默认未收藏(false)
  const [favoriteStates, setFavoriteStates] = useState(Array(6).fill(false));
  const router = useRouter();

  // 补上卡片点击逻辑(可根据需求修改)
  const handleCardPress = () => {
    // router.push('/feira-detail');
  };

  // 接收item索引,单独切换对应项的收藏状态
  const handleFavoritePress = (index) => {
    setFavoriteStates(prevStates => {
      const newStates = [...prevStates];
      newStates[index] = !newStates[index];
      return newStates;
    });
  };

  return(
      <View style={styles.container}>
          <View style={styles.header}>
              <Text style={styles.headerTitle} numberOfLines={1}>Feiras Recomendadas</Text>
              <TouchableOpacity>
                  <Text style={styles.showAll}>Mostrar Todos</Text>
              </TouchableOpacity>
          </View>

          <View>
              <FlatList 
                  data={[1,2,3,4,5,6]}
                  renderItem={({item, index}) => (
                      <CardFeirasPopulares 
                          nome={"Rua Tal"}
                          dias={['Seg', 'Qua']}
                          handleCardPress={handleCardPress}
                          handleFavoritePress={() => handleFavoritePress(index)}
                          url={favoriteStates[index] ? icons.favoritechecked : icons.favorite}
                      />
                  )}
                  horizontal
                  keyExtractor={(item) => item.toString()}
                  contentContainerStyle={{columnGap: 16}}
                  showsHorizontalScrollIndicator = {false}
              />
          </View>
      </View>
  )
}

const styles = StyleSheet.create({
  container: {
    padding: 16,
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 12,
  },
  headerTitle: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  showAll: {
    fontSize: 14,
    color: '#007AFF',
  },
});

export default FeirasPopulares;

2. CardFeirasPopulares组件(仅做简化调整)

import { View, Text, TouchableOpacity, Image, StyleSheet} from "react-native";
import { icons } from "../../../../constants";

const CardFeirasPopulares = ({nome, dias, handleCardPress, handleFavoritePress, url}) => {
    return(
        <TouchableOpacity 
            style={styles.container}
            onPress={handleCardPress}
        >
            <View >
                <Text style={styles.cardTitle}>{nome}</Text>
                <Text style={styles.cardSubtitle}>{dias[0]} - {dias[1]}</Text>
            </View>
            <TouchableOpacity onPress={handleFavoritePress} style={{padding: 8}}>
                <Image 
                    source={url}
                    resizeMode="cover"
                    style={styles.icon}
                />
            </TouchableOpacity>
        </TouchableOpacity>
    )
}

const styles = StyleSheet.create({
  container: {
    width: 180,
    padding: 12,
    backgroundColor: '#fff',
    borderRadius: 8,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  cardTitle: {
    fontSize: 16,
    fontWeight: '500',
  },
  cardSubtitle: {
    fontSize: 12,
    color: '#666',
    marginTop: 4,
  },
  icon: {
    width: 24,
    height: 24,
  },
});

export default CardFeirasPopulares;

关键修改说明:

  • 用useState创建favoriteStates数组,单独存储每个列表项的收藏状态
  • handleFavoritePress接收item索引,仅修改对应位置的状态,实现单个卡片独立切换
  • FlatList的renderItem中传递索引,根据favoriteStates[index]动态传递图片url
  • 补全未定义的handleCardPress函数,避免报错
  • 优化keyExtractor将item转为字符串,消除React警告

内容的提问来源于stack exchange,提问作者torzin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:28:19