Animated.View与useRef在子组件间莫名共享问题求助
问题原因及解决方案
核心问题1:组件类型与钩子混用
你的JournalItem代码里同时出现了函数组件的useRef钩子和类组件的方法定义(handleDelete = (food) => {}),这会破坏钩子的作用域规则,导致所有组件实例意外共享同一个translateX引用,最终只有最后一个列表项的动画被触发。
核心问题2:Key值使用不当
列表渲染时用idx作为key,当列表项被删除后,React会复用原有组件实例,进一步加剧了ref引用混乱的问题。
修复方案(函数组件版本)
将JournalItem.js改为纯函数组件,确保每个实例拥有独立的动画引用:
import { useRef } from 'react'; import { Animated } from 'react-native'; const JournalItem = ({ food, onDelete }) => { // 每个组件实例会初始化独立的Animated.Value引用 const translateX = useRef(new Animated.Value(0)).current; const handleDelete = () => { Animated.timing(translateX, { toValue: -width, duration: 350, useNativeDriver: false, }).start(() => { // 触发父组件的删除逻辑 onDelete(food); }); }; return ( <Swipeable renderRightActions={renderRightActions} overshootRight={false} onSwipeableOpen={handleDelete} rightThreshold={75} containerStyle={[ { transform: [{ translateX }], }, ]} > {/* 组件内容 */} </Swipeable> ); }; export default JournalItem;
同时修改列表渲染的key值,使用food的唯一标识(如food.id)代替索引:
{formattedJournal[meal].map((food, idx, arr) => { const isLast = idx === arr.length - 1; return ( <View key={food.id}> {/* 改用唯一ID作为key */} <JournalItem isLast={isLast} idx={idx} food={food} onDelete={/* 传入父组件的删除函数 */} /> </View> ); })}
修复方案(类组件版本)
如果坚持使用类组件,替换useRef为createRef来保证实例独立:
import { Component, createRef } from 'react'; import { Animated } from 'react-native'; class JournalItem extends Component { constructor(props) { super(props); // 每个类实例拥有独立的动画引用 this.translateX = createRef(new Animated.Value(0)); } handleDelete = () => { Animated.timing(this.translateX.current, { toValue: -width, duration: 350, useNativeDriver: false, }).start(() => { this.props.onDelete(this.props.food); }); }; render() { return ( <Swipeable renderRightActions={renderRightActions} overshootRight={false} onSwipeableOpen={this.handleDelete} rightThreshold={75} containerStyle={[ { transform: [{ translateX: this.translateX.current }], }, ]} > {/* 组件内容 */} </Swipeable> ); } } export default JournalItem;
内容的提问来源于stack exchange,提问作者Marc Fletcher
相关产品推荐
相关产品推荐

