oblador / react-native-animatable

Standard set of easy to use animations and declarative transitions for React Native
MIT License
9.81k stars 702 forks source link

How to use Animatable.View in Typescript #313

Open matheuspelegrino opened 4 years ago

matheuspelegrino commented 4 years ago

Code:


import * as Animatable from 'react-native-animatable';

const Connection: React.FC = () => {
  const animatableRef = useRef<Animatable.View>(null);
// not working
// const animatableRef = useRef<Animatable.View | null>(null);
// const animatableRef = useRef<Animatable.View | null>();
// const animatableRef = useRef<Animatable.View>();

   [...] 
  return (
    <Animatable.View
      ref={animatableRef}
      animation="slideInDown"
      style={{ zIndex: 10 }}
    >

        <Text>Say hello</Text>

    </Animatable.View>
  );
};

Error in ref property


No overload matches this call.
  Overload 1 of 2, '(props: AnimatableProperties<ViewStyle> & ViewProps, context?: any): ClassicComponent<AnimatableProperties<ViewStyle> & ViewProps, any>', gave the following error.
    O tipo 'RefObject<View>' não pode ser atribuído ao tipo 'string | ((instance: ClassicComponent<AnimatableProperties<ViewStyle> & ViewProps, any> | null) => void) | RefObject<...> | null | undefined'.
      O tipo 'RefObject<View>' não pode ser atribuído ao tipo 'RefObject<ClassicComponent<AnimatableProperties<ViewStyle> & ViewProps, any>>'.
        Type 'AnimatableComponent<ViewProps, ViewStyle>' is missing the following properties from type 'ClassicComponent<AnimatableProperties<ViewStyle> & ViewProps, any>': replaceState, isMounted, context, setState, and 4 more.
  Overload 2 of 2, '(props: AnimatableProperties<ViewStyle> & ViewProps, context?: any): Component<AnimatableProperties<ViewStyle> & ViewProps, any, any>', gave the following error.
    O tipo 'RefObject<View>' não pode ser atribuído ao tipo 'string | ((instance: Component<AnimatableProperties<ViewStyle> & ViewProps, any, any> | null) => void) | RefObject<Component<AnimatableProperties<...> & ViewProps, any, any>> | null | undefined'.
      O tipo 'RefObject<View>' não pode ser atribuído ao tipo 'RefObject<Component<AnimatableProperties<ViewStyle> & ViewProps, any, any>>'.
        Type 'AnimatableComponent<ViewProps, ViewStyle>' is missing the following properties from type 'Component<AnimatableProperties<ViewStyle> & ViewProps, any, any>': context, setState, forceUpdate, render, and 2 more.ts(2769)
index.d.ts(145, 9): The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<ClassicComponent<AnimatableProperties<ViewStyle> & ViewProps, any>> & Readonly<...> & Readonly<...>'
index.d.ts(145, 9): The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<AnimatableProperties<ViewStyle> & ViewProps, any, any>> & Readonly<...> & Readonly<...>'
andrico1234 commented 4 years ago

I also came across this issue.

I removed the type and it works


const Connection: React.FC = () => {
  const animatableRef = useRef(null);

  return (
    <Animatable.View
      ref={animatableRef}
      animation="slideInDown"
      style={{ zIndex: 10 }}
    >

        <Text>Say hello</Text>

    </Animatable.View>
  );
}

I have faith in TypeScript's type inference that I don't need to explicitly define the type.

Edit

Completely ignore me, it just returns a RefType<any> or something along those lines. I was wrong about the type inference!

matt-pawley commented 4 years ago

Not sure if its the best solution, but I find the following works well:

const animatableRef = useRef<Animatable.View & View>(null);
matheuspelegrino commented 4 years ago

Awesome, it worked @toughdeveloper!

In theory, it doesn't have to be necessary, does it?

Animatable.View returns or must reference a View Props:

export type View = AnimatableComponent <ViewProperties, ViewStyle>; 

Or am I wrong?

ryoid commented 4 years ago

@toughdeveloper solution worked for me.

However, when using it with custom components doesn't seem to work. I am trying to use it with react-native-fast-image anyone know how I should be doing it?

const AnimatedImage = Animatable.createAnimatableComponent(FastImage);

const imageRef = React.useRef<typeof AnimatedImage>(null);
No overload matches this call.
  Overload 1 of 2, '(props: AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, context?: any): ClassicComponent<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any>', gave the following error.
    Type 'RefObject<AnimatableComponent<FastImageProperties, StyleProp<ImageStyle>>>' is not assignable to type 'string | ((instance: ClassicComponent<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any> | null) => void) | RefObject<...> | null | undefined'.
      Type 'RefObject<AnimatableComponent<FastImageProperties, StyleProp<ImageStyle>>>' is not assignable to type 'RefObject<ClassicComponent<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any>>'.
        Type 'AnimatableComponent<FastImageProperties, StyleProp<ImageStyle>>' is missing the following properties from type 'ClassicComponent<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any>': replaceState, isMounted, context, setState, and 4 more.
  Overload 2 of 2, '(props: AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, context?: any): Component<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any, any>', gave the following error.
    Type 'RefObject<AnimatableComponent<FastImageProperties, StyleProp<ImageStyle>>>' is not assignable to type 'string | ((instance: Component<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any, any> | null) => void) | RefObject<...> | null | undefined'.
      Type 'RefObject<AnimatableComponent<FastImageProperties, StyleProp<ImageStyle>>>' is not assignable to type 'RefObject<Component<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any, any>>'.
        Type 'AnimatableComponent<FastImageProperties, StyleProp<ImageStyle>>' is missing the following properties from type 'Component<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any, any>': context, setState, forceUpdate, render, and 2 more.ts(2769)
index.d.ts(145, 9): The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<ClassicComponent<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any>> & Readonly<...> & Readonly<...>'
index.d.ts(145, 9): The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<AnimatableProperties<StyleProp<ImageStyle>> & FastImageProperties, any, any>> & Readonly<...> & Readonly<...>'
probablykabari commented 4 years ago

Same with using custom animations. Type error on the animation property.

<Animatable.Image 
  animation={{ 
    from: { rotateY: '0deg' }, 
    to: { rotateY: '359deg'} 
   }}
   />
darron1217 commented 3 years ago

Any update on this issue?

isghanim commented 2 years ago

@toughdeveloper solution worked for me.

However, when using it with custom components doesn't seem to work. I am trying to use it with react-native-fast-image anyone know how I should be doing it?

const AnimatedImage = Animatable.createAnimatableComponent(FastImage);

const imageRef = React.useRef<typeof AnimatedImage>(null);

@ryoid I was having a similar issue, although I'm using react-native-reanimated (version 2.2.0) and what I'm doing is a bit different. I managed to fix the error by casting the FastImage:

const AnimatedFastImage = Animated.createAnimatedComponent(
    FastImage as ComponentClass<FastImageProps, unknown>
);

This is the error I was getting:

No overload matches this call.
  Overload 1 of 2, '(component: ComponentClass<FastImageProps, any>, options?: Options<FastImageProps> | undefined): ComponentClass<AnimateProps<FastImageProps>, any>', gave the following error.
    Argument of type 'ComponentType<FastImageProps> & FastImageStaticProperties' is not assignable to parameter of type 'ComponentClass<FastImageProps, any>'.
      Type 'FunctionComponent<FastImageProps> & FastImageStaticProperties' is not assignable to type 'ComponentClass<FastImageProps, any>'.
        Type 'FunctionComponent<FastImageProps> & FastImageStaticProperties' provides no match for the signature 'new (props: FastImageProps, context?: any): Component<FastImageProps, any, any>'.
  Overload 2 of 2, '(component: FunctionComponent<FastImageProps>, options?: Options<FastImageProps> | undefined): FunctionComponent<AnimateProps<FastImageProps>>', gave the following error.
    Argument of type 'ComponentType<FastImageProps> & FastImageStaticProperties' is not assignable to parameter of type 'FunctionComponent<FastImageProps>'.
      Type 'ComponentClass<FastImageProps, any> & FastImageStaticProperties' is not assignable to type 'FunctionComponent<FastImageProps>'.
        Type 'ComponentClass<FastImageProps, any> & FastImageStaticProperties' provides no match for the signature '(props: PropsWithChildren<FastImageProps>, context?: any): ReactElement<any, any> | null'.ts(2769)

So I cast the FastImage as the type that the parameter seemed to be expecting.

dennisbouwpas commented 2 years ago
  const OptionsAnimationRef = React.useRef<Animatable.View>();

Seems to be working but when I am trying

  OptionsAnimationRef.current?.slideInLeft(300);

I have

  Cannot invoke an object which is possibly 'undefined'.ts(2722)

Anyone knows how to fix this ?

alielmajdaoui commented 2 years ago

I have been using type casting with React.RefObject<T> so far and it works.

const Comp = () => {
    const animatableViewRef = useRef() as React.RefObject<Animatable.View & View>;

    React.useEffect(() => {
        if (
            animatableViewRef.current &&
            typeof animatableViewRef.current.bounceIn === 'function'
        ) {
            animatableViewRef.current.bounceIn(1000);
        }
    }, []);

    return <Animatable.View>{/* ... */}</Animatable.View>;
};
betopompolo commented 1 year ago

any updates?

marioteik commented 10 months ago

I'm doing this and it's an ugly solution:

// from another file so I can reuse it
export type AnimatableViewRef = Animatable.View & View;

// on my component
const viewRef = useRef<AnimatableViewRef>(null);

useEffect(() => {
  if (focused) {
    viewRef.current?.zoomIn?.(1000);
  } else {
    viewRef.current?.zoomOut?.(1000);
  }
}, [focused]);

We should have an AnimatableViewRef type properly typed.

In my case, there is no time that zoomIn and zoomOut are undefined if the viewRef.current is not undefined, so we should not have to check zoomIn?.(n) in runtime.

pachun commented 5 months ago

Also noticing the TS error that @dennisbouwpas is seeing. Using typescript 5.1.3.

mkamran67 commented 3 months ago

Having TS errors with const zoomOut = { 0: { opacity: 1, scale: 1, }, 0.5: { opacity: 1, scale: 0.3, }, 1: { opacity: 0, scale: 0, }, };

passed in as an animation, this is from the example.

Blue-Marvel commented 1 month ago

Casting zoomOut as CustomAnimation works with this from my end

`import * as Animatable from "react-native-animatable";

const zoomIn = { 0: { scale: 0.9, }, 1: { scale: 1, }, } as Animatable.CustomAnimation; const zoomOut = { 0: { scale: 1, }, 1: { scale: 0.9, }, } as Animatable.CustomAnimation;

const TrendingItems: FC<{ activeItem: HomeHostData; items: HomeHostData }> = ({ activeItem: acitveItem, items: items, }) => { return ( <Animatable.View className="mr-5" animation={acitveItem === items ? zoomIn : zoomOut} duration={500}

</Animatable.View> ); };`

Got it from this repo though:https://github.com/ashot-israelyan/expo-movie-app