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

React Native旧Animated迁移Reanimated:点击动画无法隔离单个项

问题解决:Reanimated迁移后FlatList点击项无法隔离动画

问题原因

你当前代码的核心问题是:rotation这个useSharedValue定义在App根组件中,所有FlatList的Item组件共享同一个动画状态值。点击任意项时修改的都是同一个全局rotation,自然所有项会同步触发动画——这和旧Animated代码里每个Item独立维护Animated.Value的逻辑完全相反,旧代码的隔离性正是源于每个Item拥有专属的动画状态。

修复方案

把动画相关的状态与逻辑移至Item组件内部,让每个Item拥有独立的共享值和动画处理函数,点击单个Item时仅修改自身的动画状态,不会影响其他项。同时修正keyExtractor的错误(原写法会导致列表key无效)。

修改后的完整代码

import React from 'react';
import { SafeAreaView, FlatList, View, Text } from 'react-native';
import Animated, { useSharedValue, useAnimatedStyle, withSequence, withTiming, withRepeat, Easing } from 'react-native-reanimated';

const ANGLE = 10;
const TIME = 100;
const EASING = Easing.elastic(1.5);

const items = [
  { id: 1, name: 'name 1' },
  { id: 2, name: 'name 2' },
  { id: 3, name: 'name 3' },
  { id: 4, name: 'name 4' },
];

// 独立封装Item组件,内部维护专属动画状态
const Item = ({ item }) => {
  // 每个Item实例拥有独立的共享值
  const rotation = useSharedValue(0);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ rotateZ: `${rotation.value}deg` }],
  }));

  const handlePress = () => {
    rotation.value = withSequence(
      withTiming(-ANGLE, { duration: TIME / 2, easing: EASING }),
      withRepeat(
        withTiming(ANGLE, {
          duration: TIME,
          easing: EASING,
        }),
        7,
        true
      ),
      withTiming(0, { duration: TIME / 2, easing: EASING })
    );
  };

  return (
    <View style={{ margin: 10 }}>
      <Animated.View style={animatedStyle}>
        <Text onPress={handlePress}>{item.name}</Text>
      </Animated.View>
    </View>
  );
};

export default function App() {
  return (
    <SafeAreaView style={{ flex: 1 }}>
      <FlatList
        numColumns={4}
        data={items}
        renderItem={({ item }) => <Item item={item} />}
        keyExtractor={item => item.id.toString()} // 使用唯一id作为列表项key
      />
    </SafeAreaView>
  );
}

关键修改点

  • 动画状态私有化:将rotation共享值、animatedStyle、handlePress全部移入Item组件,确保每个Item实例拥有独立的动画状态。
  • 修正列表key:把无效的keyExtractor改为使用item的唯一id,保证FlatList的正确渲染与项复用。
  • 组件结构优化:将Item组件从App内部抽离,符合组件封装逻辑,避免内部组件重复创建的性能问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 13:25:12