我使用 Tap Gesture Handler 和 Reanimated 创建了一个高亮组件,一切都很好,但是当我们需要类或组件的当前状态时它不起作用,它每次都需要初始状态
这是组件
高亮.tsx
import React, {ReactNode} from 'react';
import {ViewStyle, StyleSheet, StyleProp} from 'react-native';
import {TapGestureHandler, State} from 'react-native-gesture-handler';
import Animated, {Easing} from 'react-native-reanimated';
import {
timing,
contains,
useValue,
useClock,
} from 'react-native-redash';
export interface Props {
style?: StyleProp<ViewStyle>;
underlay?: string;
onPress?: () => void;
children?: ReactNode;
disabled?: boolean;
state?: Animated.Value<number>;
val?: Animated.Value<number>;
onPressIn?: () => void;
onPressOut?: () => void;
testID?: string;
onLongPress?: () => void;
}
const {
event,
useCode,
block,
cond,
eq,
set,
call,
onChange,
} = Animated;
const {BEGAN, FAILED, CANCELLED, END, UNDETERMINED} = State;
/**
* Re Highlight
*/
export default ({
onPress = () => {},
onPressIn = () => {},
onPressOut = () => {},
style,
state: st,
val,
children,
underlay = 'rgba(63, 118, 230, 0.1)',
testID,
}: Props) => {
console.log('onPress:', onPress)
// Animated Values
const opacity = val || useValue(0);
const clock = useClock();
const shouldSpring = useValue(-1);
const state = st || useValue(UNDETERMINED);
useCode(
() =>
block([
cond(eq(state, BEGAN), set(shouldSpring, 1)),
cond(contains([FAILED, CANCELLED], state), set(shouldSpring, 0)),
onChange(
state,
cond(
eq(state, END),
call([], onPress),
),
),
cond(eq(state, END), set(shouldSpring, 0)),
onChange(
shouldSpring,
cond(eq(shouldSpring, 1), call([], onPressIn), call([], onPressOut)),
),
cond(
eq(shouldSpring, 1),
set(
opacity,
timing({
clock,
from: opacity,
to: 1,
duration: 100,
easing: Easing.inOut(Easing.ease),
}),
),
),
cond(
eq(shouldSpring, 0),
set(
opacity,
timing({
clock,
from: opacity,
to: 0,
duration: 400,
easing: Easing.inOut(Easing.ease),
}),
),
),
]),
[],
);
return (
<TapGestureHandler
onHandlerStateChange={event([
{
nativeEvent: {
state: state,
},
},
])}>
<Animated.View {...{testID}} style={[style, {overflow: 'hidden'}]}>
{children}
<Animated.View
pointerEvents="none"
style={{
...styles.overlay,
opacity,
backgroundColor: underlay,
}}
/>
</Animated.View>
</TapGestureHandler>
);
};
const styles = StyleSheet.create({
overlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
container: {
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'center',
},
});
我阅读了 useCode 文档并将 onPress、OnPressIn、OnPressOut 作为依赖项添加到 useCode 挂钩,
useCode(block([]), [onPress, onPressIn, onPressOut])
如果我们在 onPress 函数中设置状态,它将产生无限循环......