Re-usable한 Wrapper 컴포넌트 제작
GestureContainer.tsx
import React from 'react';
import GestureRecognizer from 'react-native-swipe-gestures';
import {GestureContainerProps} from './types';
export default function GestureContainer({
children,
onSwipeUp = gestureState => console.log('state : ', gestureState),
onSwipeDown = gestureState => console.log('state : ', gestureState),
onSwipeLeft = gestureState => console.log('state : ', gestureState),
onSwipeRight = gestureState => console.log('state : ', gestureState),
velocityThreshold = 0.3,
directionalOffsetThreshold = 80,
}: GestureContainerProps) {
//
const config = {
velocityThreshold,
directionalOffsetThreshold,
};
return (
<GestureRecognizer
onSwipeUp={state => onSwipeUp(state)}
onSwipeDown={state => onSwipeDown(state)}
onSwipeLeft={state => onSwipeLeft(state)}
onSwipeRight={state => onSwipeRight(state)}
config={config}
style={[]}>
{children}
</GestureRecognizer>
);
}
types.ts
import {ReactElement} from 'react';
import {PanResponderGestureState} from 'react-native';
export type SwipeDirections =
| 'SWIPE_UP'
| 'SWIPE_DOWN'
| 'SWIPE_LEFT'
| 'SWIPE_RIGHT';
export type GestureContainerProps = {
children: ReactElement;
onSwipeUp?: (gestureState?: PanResponderGestureState) => void;
onSwipeDown?: (gestureState?: PanResponderGestureState) => void;
onSwipeLeft?: (gestureState?: PanResponderGestureState) => void;
onSwipeRight?: (gestureState?: PanResponderGestureState) => void;
velocityThreshold?: number;
directionalOffsetThreshold?: number;
};
export type GestureHandler = (gestureState: PanResponderGestureState) => void;
커스텀 wrapper 컴포넌트 활용 예시
GestureExm.tsx
import React, {useState} from 'react';
import {View, Text, StyleSheet, Image, Pressable} from 'react-native';
import * as Animatable from 'react-native-animatable';
import GestureContainer from './GestureContainer';
const summary = require('../images/Summary.png');
const editImg = require('../images/Edit.png');
const deleteImg = require('../images/Delete.png');
export default function GestureExm() {
const [isLeft, setIsLeft] = useState(false);
const onLeft = () => {
setIsLeft(true);
console.log('left');
};
const onRight = () => {
setIsLeft(false);
console.log('right');
};
const onEdit = () => {
console.log('수정 누름');
};
const onDelete = () => {
console.log('삭제 누름');
};
return (
<GestureContainer onSwipeLeft={onLeft} onSwipeRight={onRight}>
<View style={{flexDirection: 'row', width: '100%', padding: 10}}>
<View style={[styles.summary, isLeft && styles.left]}>
<Image source={summary} />
</View>
{isLeft && (
<>
<Animatable.View
animation="fadeInLeft"
duration={500}
style={{zIndex: 1}}>
<Pressable style={styles.edit} onPress={onEdit}>
<Image source={editImg} />
<Text style={styles.buttonText}>수정</Text>
</Pressable>
</Animatable.View>
<Animatable.View
animation="fadeInLeft"
duration={500}
delay={100}
style={{zIndex: 0}}>
<Pressable style={styles.delete} onPress={onDelete}>
<Image source={deleteImg} />
<Text style={styles.buttonText}>삭제</Text>
</Pressable>
</Animatable.View>
</>
)}
</View>
</GestureContainer>
);
}
const styles = StyleSheet.create({
summary: {
zIndex: 3,
backgroundColor: 'white',
borderRadius: 10,
overflow: 'hidden',
},
edit: {
backgroundColor: '#A8A7B5',
marginLeft: -8,
zIndex: 1,
padding: 10,
paddingLeft: 15,
borderTopRightRadius: 10,
borderBottomRightRadius: 10,
justifyContent: 'center',
},
delete: {
backgroundColor: '#E00C3E',
marginLeft: -8,
zIndex: 0,
padding: 10,
paddingLeft: 15,
borderTopRightRadius: 10,
borderBottomRightRadius: 10,
justifyContent: 'center',
},
left: {marginLeft: -40},
buttonText: {color: 'white', fontSize: 14, fontWeight: '600', marginTop: 6},
});