1

我使用 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 函数中设置状态,它将产生无限循环......

4

0 回答 0