Pass functional component to Animated.createAnimatedComponent
Asked Answered
A

3

6

If you try to pass functional (non react class) component to Animated.createAnimatedComponent it throws an error that says

Stateless functional components are invalid as children of createAnimatedComponent

Coming from an app that uses react hooks, basically all of my component are functional.

Is there a way / helper that can allow to pass these to createAnimatedComponent without wrapping them in Animated.View or even just View?

Here is an example of component that I want to make animatable

function MyComponent({ someProp }) {
  const [counter, setCounter] = useState(0);

  return (
    <View>
      <Text>{counter}</Text>
    </View>
  );

}
Acroter answered 5/8, 2019 at 13:14 Comment(6)
What is useState(0) ?Internode
@hongdevelop React Hooks.Hemangioma
@hongdevelop here is more info on hooks reactjs.org/docs/hooks-intro.htmlAcroter
Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions. (There is just one other valid place to call Hooks — your own custom Hooks.Internode
They say you have to make your own Hooks.Internode
@hongdevelop What are you saying? MyComponent is a React component...Dunderhead
T
5

As far as I can tell, your options are:

1) Change to class component

2) Wrap your component in a View which you then animate

3) Use react-native-animatable (or a solution similar as this offers): check here for a combination of the library and refs

4) Maybe a solution similar to this one would suit you better. Combination of useRef and useEffect.

Tyburn answered 6/8, 2019 at 7:14 Comment(2)
another way is you can use React.forwardRefMarseilles
github.com/facebook/react-native/issues/…Marseilles
F
9

How about this HOC

export function withAnimated(
  WrappedComponent: React.ComponentType<any>,
): ComponentType {
  const displayName =
    WrappedComponent.displayName || WrappedComponent.name || 'Component';

  class WithAnimated extends React.Component {
    static displayName = `WithAnimated(${displayName})`;

    render(): React.ReactNode {
      return <WrappedComponent {...this.props} />;
    }
  }

  return Animated.createAnimatedComponent(WithAnimated);
}

Usage

export const AnimatedGradientButton = withAnimated(GradientButton);

Feticide answered 9/3, 2020 at 7:7 Comment(0)
T
5

As far as I can tell, your options are:

1) Change to class component

2) Wrap your component in a View which you then animate

3) Use react-native-animatable (or a solution similar as this offers): check here for a combination of the library and refs

4) Maybe a solution similar to this one would suit you better. Combination of useRef and useEffect.

Tyburn answered 6/8, 2019 at 7:14 Comment(2)
another way is you can use React.forwardRefMarseilles
github.com/facebook/react-native/issues/…Marseilles
A
0

Adding to @MJ Studio's answer to add prop type assertion:

export function withAnimated<T extends object>(
  WrappedComponent: ComponentType<T>
): ComponentClass<AnimatedProps<T>, any> {
  const displayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';

  class WithAnimated extends Component<T> {
    static displayName = `WithAnimated(${displayName})`;

    render(): ReactNode {
      return <WrappedComponent {...this.props} />;
    }
  }

  return Animated.createAnimatedComponent<T>(WithAnimated);
}

Usage:

const MyAnimatedComp = withAnimated(MyCompWithCustomProps);
// MyAnimatedComp is typed as React.ComponentClass<AnimatedProps<MyCompCustomProps>, any>
Aerobiology answered 30/5 at 18:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.