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

如何用useState实现删除收藏项时仅显示对应项的提示文本

问题描述

我尝试在从收藏夹中移除电影项时,仅对被移除的项显示“Removed from favorites”文本,但目前的条件渲染逻辑导致所有渲染的项都被隐藏。我意识到是使用了全局state,替换了所有项而非仅目标项。相关代码如下:

import React, { useEffect, useRef, useState } from 'react'
import { View, StyleSheet, Text, Image } from 'react-native'
import { FavouriteStackParams, Movie, NavigationProps } from '../types'
import { FlatList } from 'react-native-gesture-handler'
import { MaterialCommunityIcons } from '@expo/vector-icons'
import { StorageResources } from '../api'
import LoaderBox from './LoaderBox'
import navigation from '../navigation'
import { useFocusEffect } from '@react-navigation/native'

export default function FavouriteBox() {
  const [favoritesFilm, setFavorite] = useState<Movie[]>([])
  const [isLoadingFav, setIsLoadingFav] = useState(true)
  const [titleText, setTitleText] = useState(false)

  useFocusEffect(
    React.useCallback(() => {
      setIsLoadingFav(true)

      getFav()
      return () => {
        
      }
    }, [navigation])
  )

  async function removeMovie(id: Movie) {
    const value = await StorageResources.storageGet('favmovies')
    const alteredValue = value.filter(function (e: { id: any }) {
      return e.id !== id
    })
    StorageResources.storageSave('favmovies', alteredValue)
    setTitleText(true)
  }

  async function getFav() {
    const favorites = await StorageResources.storageGet('favmovies')
    setFavorite(favorites)
    setIsLoadingFav(false)
    setTitleText(false)
  }

  const renderItemFav = ({ item }: any) => (
    <FavMovie name={item.name} title={item.title} poster_path={item.poster_path} id={item.id} />
  )
  const FavMovie = ({ title, poster_path, name, id }: any) => (
    <View style={styles.wrap}>
      {titleText && <Text style={styles.text}>Removed from favorites</Text>}
      {!titleText && (
        <>
          <Image
            style={styles.image}
            source={{
              uri: `https://image.tmdb.org/t/p/w500/${poster_path}`,
            }}
          />
          <Text style={styles.fav}>{title}</Text>
          <Text style={styles.fav}>{name}</Text>
          <MaterialCommunityIcons
            onPress={() => {
              removeMovie(id)
            }}
            name="bookmark-minus-outline"
            style={styles.book}
          />
        </>
      )}
    </View>
  )
}
解决方案

核心问题是全局布尔状态titleText控制了所有项的显示,要改成跟踪单个被移除电影的ID,只对目标项触发提示:

  1. 替换全局状态
    把原来的titleText布尔状态改成存储被移除ID的数组,用来记录哪些电影刚被移除:
// 替换原有的const [titleText, setTitleText] = useState(false)
const [removedMovieIds, setRemovedMovieIds] = useState<number[]>([])
  1. 修正移除函数
    修改removeMovie,直接更新本地收藏列表(不用重新从存储读取),同时记录被移除的ID,还可以加个定时器让提示自动消失:
async function removeMovie(id: number) {
  // 先更新本地状态,立即反馈给用户
  const updatedFavorites = favoritesFilm.filter(movie => movie.id !== id)
  setFavorite(updatedFavorites)
  // 保存到本地存储
  await StorageResources.storageSave('favmovies', updatedFavorites)
  // 将当前移除的ID加入提示列表
  setRemovedMovieIds(prev => [...prev, id])
  // 可选:2秒后自动移除提示,让项消失或恢复(根据需求调整时间)
  setTimeout(() => {
    setRemovedMovieIds(prev => prev.filter(movieId => movieId !== id))
  }, 2000)
}

注意:这里修正了参数类型,原来的id: Movie是错误的,实际传的是数字ID,所以改成id: number。

  1. 修改项的渲染逻辑
    让FavMovie组件只根据当前项的ID是否在removedMovieIds里来显示提示,不再依赖全局布尔值:
const FavMovie = ({ title, poster_path, name, id }: { title: string; poster_path: string; name: string; id: number }) => (
  <View style={styles.wrap}>
    {/* 只有当前电影ID在移除列表时才显示提示 */}
    {removedMovieIds.includes(id) && <Text style={styles.text}>Removed from favorites</Text>}
    {/* 不在移除列表时显示电影内容 */}
    {!removedMovieIds.includes(id) && (
      <>
        <Image
          style={styles.image}
          source={{
            uri: `https://image.tmdb.org/t/p/w500/${poster_path}`,
          }}
        />
        <Text style={styles.fav}>{title}</Text>
        <Text style={styles.fav}>{name}</Text>
        <MaterialCommunityIcons
          onPress={() => {
            removeMovie(id)
          }}
          name="bookmark-minus-outline"
          style={styles.book}
        />
      </>
    )}
  </View>
)
  1. 清空移除记录
    在getFav函数里清空removedMovieIds,避免回到页面后旧的提示还显示:
async function getFav() {
  const favorites = await StorageResources.storageGet('favmovies')
  setFavorite(favorites)
  setIsLoadingFav(false)
  setRemovedMovieIds([]) // 清空移除记录
}

这样修改后,只有被点击移除的那项会显示提示,其他项不受影响,而且提示会自动消失(如果加了定时器),同时本地状态和存储也能正确同步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:50:38