Код-ревью Middle Анимации и жесты обновлено
Код-ревью: перетаскиваемая карточка
Вопрос
Компонент перетаскиваемой карточки. Найдите проблемы производительности и логики.
export function DraggableCard() {
const [x, setX] = useState(0);
const pan = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: () => true,
onPanResponderMove: (_, g) => setX(g.dx),
onPanResponderRelease: () => setX(0),
}),
).current;
const opacity = useRef(new Animated.Value(1)).current;
useEffect(() => {
Animated.timing(opacity, { toValue: 0.5, duration: 300, useNativeDriver: true }).start();
});
return (
<Animated.View {...pan.panHandlers} style={{ transform: [{ translateX: x }], opacity, width: 300 }}>
<HeavyContent />
</Animated.View>
);
}
Коротко
Перетаскивание делают так, чтобы React не участвовал в каждом кадре: Gesture.Pan меняет shared value, useAnimatedStyle применяет сдвиг на UI-потоке, возврат через withSpring. Жест активируется только по горизонтали (activeOffsetX).
Что должен найти ревьюер
- Производительностьстрока 6
setStateна каждое движение пальца: перерисовка компонента с тяжёлым содержимым 60+ раз в секунду через JS-поток. Нужен Gesture Handler + Reanimated (илиAnimated.event). - Ошибкастрока 5
onMoveShouldSetPanResponder: () => trueперехватывает любое движение, включая вертикальную прокрутку родительского списка. - Стильстрока 7Возврат на место без анимации: карточка прыгает. Нужна пружина (
withSpringилиAnimated.spring). - Ошибкастрока 11Эффект без зависимостей запускает анимацию на каждом рендере, а рендеров при перетаскивании десятки.
- Производительностьстрока 16
HeavyContentперерисовывается при каждом движении: его нужно мемоизировать или убрать перерисовки родителя.
Разбор
Перетаскивание делают так, чтобы React не участвовал в каждом кадре: Gesture.Pan меняет shared value, useAnimatedStyle применяет сдвиг на UI-потоке, возврат через withSpring. Жест активируется только по горизонтали (activeOffsetX).
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.