React Native+Reanimated动态渲染报错:Hook渲染数量不一致
解决React Native + Reanimated动态渲染时Hook数量不一致的问题
问题根源
你遇到的报错核心是违反了React Hook的核心规则:Hook必须在每次渲染时以完全相同的顺序调用。之前的写法里,你根据hand数组的长度动态生成useSharedValue数组,数组元素增减会导致Hook的调用数量前后不一致,直接触发Rendered more hooks than during the previous render错误。
两种可行解决方案
方案1:用单个useSharedValue存储所有元素的动画状态
把每个卡片的偏移量存在一个对象里,用卡片的唯一ID作为键,这样始终只使用一个useSharedValue,Hook数量不会随数组变化而改变:
import { useSharedValue, useEffect } from 'react-native-reanimated'; const CardList = ({ hand }) => { // 用对象存储每个卡片的偏移量,键为卡片ID const offsets = useSharedValue({}); // 当hand数组更新时,为新加入的卡片初始化偏移量 useEffect(() => { hand.forEach(card => { if (!offsets.value[card.id]) { // 初始化新卡片的默认偏移值 offsets.value[card.id] = { x: 0, y: 0 }; } }); }, [hand]); return ( <View> {hand.map(card => { const cardOffset = offsets.value[card.id]; return ( <Animated.View key={card.id} style={{ transform: [ { translateX: cardOffset.x }, { translateY: cardOffset.y } ] }} > {/* 卡片内容 */} </Animated.View> ); })} </View> ); };
方案2:将动画逻辑封装到子组件中
把每个卡片的useSharedValue放到独立的子组件里,父组件只负责循环渲染子组件。这样父组件的Hook数量始终固定,子组件的Hook由React独立管理,完全符合规则:
// 子组件:单个卡片,内部管理自己的动画状态 const CardItem = ({ card }) => { // 每个卡片单独拥有自己的useSharedValue const offset = useSharedValue({ x: 0, y: 0 }); // 这里可以写卡片的动画逻辑,比如拖拽、入场动画等 // ... return ( <Animated.View style={{ transform: [ { translateX: offset.value.x }, { translateY: offset.value.y } ] }} > {/* 卡片内容,比如图片、文字 */} </Animated.View> ); }; // 父组件:卡片列表 const CardList = ({ hand }) => { return ( <View> {hand.map(card => ( // 必须用卡片的唯一ID作为key,不能用index <CardItem key={card.id} card={card} /> ))} </View> ); };
注意事项
- 不管用哪种方案,渲染列表时必须使用卡片的唯一标识(比如
card.id)作为key,不能用数组索引,否则React会错误地复用组件,导致动画状态混乱。 - 如果卡片有删除操作,方案1里可以在
useEffect里清理掉已删除卡片的偏移量,避免对象冗余:useEffect(() => { // 清理已删除卡片的偏移量 const existingIds = hand.map(card => card.id); Object.keys(offsets.value).forEach(id => { if (!existingIds.includes(id)) { delete offsets.value[id]; } }); // 初始化新卡片的偏移量 hand.forEach(card => { if (!offsets.value[card.id]) { offsets.value[card.id] = { x: 0, y: 0 }; } }); }, [hand]);
内容的提问来源于stack exchange,提问作者jcboz
相关产品推荐
相关产品推荐

