React-native-reanimated: V2: interpolateNode causes crash

Created on 8 Jun 2020  路  22Comments  路  Source: software-mansion/react-native-reanimated

Description

when using interpolateNode the app crashes

Steps To Reproduce

  1. create an interpolateNode value and assign it to useAnimatedStyle
const width = interpolateNode(tY.value, {
    inputRange: [10, 100],
    outputRange: [40, 200],
    Extrapolate: Extrapolate.CLAMP,
  });

Reanimated 2

馃彔 Reanimated2 馃悶 Bug

Most helpful comment

The interpolate function in Reanimated2 is a pure function. It takes arguments and returns a value.

You have two options here:

  1. Use and log interpolate inside the worklet (useAnimatedStyle or inside any of the gesture handlers)
  2. Wrap that interpolate call with useDerivedValue - it returns a shared value, so make sure to use .value:
const width = useDerivedValue(() => {
  return interpolate(...);
});

All 22 comments

You're mixing Reanimated 1 and reanimated 2, right? This may be not supported when you're using nodes in new hooks

No the tY in the example is equal to useSharedValue().

Can you provide an example of using interpolation in v2 please?

const聽width聽=聽interpolate(
    tY.value,
聽聽聽聽[10,聽100],
聽聽聽聽[40,聽200],
聽聽聽聽Extrapolate.CLAMP,
);

No luck @terrysahaidak

I tried the following

const width = interpolateNode(tY.value, {
    inputRange: [0, 100],
    outputRange: [10, 200],
    Extrapolate: Extrapolate.CLAMP,
  });

also

const width = interpolate(tY.value, {
    inputRange: [0, 100],
    outputRange: [10, 200],
    Extrapolate: Extrapolate.CLAMP,
  });

and when using any of them in the useAnimatedStyle or direclty in the style of the component, it crashes, result of console.log of for the one you sent me (interpolate, not intepolateNode) was NaN,
also console logging the result of interpolateNode causes crash

Please, carefully read my suggestion. The interpolation in Reanimated2 takes 4 parameters: sharedValue's value, array of input, array of output and extrapolate. You're using 2 parameters instead and passing the object as a second one. That's how interpolate node works

Thank you @terrysahaidak , sorry my bad didn't notice the change, Currently I do the following and I don't see any update in the interpolated value

const width = interpolate(tY.value, [10, 100], [40, 200], Extrapolate.CLAMP);

here is the log:
image

Could you post a code snipped with those logs and useAnimatedStyle?

Yes, sure. @terrysahaidak here you go.

import React from 'react';
import {StyleSheet, View, Text} from 'react-native';
import Animated, {
  withSpring,
  useSharedValue,
  useAnimatedStyle,
  useAnimatedGestureHandler,
  interpolate,
  Extrapolate,
} from 'react-native-reanimated';
import {PanGestureHandler} from 'react-native-gesture-handler';

const App = () => {
  const tY = useSharedValue(0);
  const width = interpolate(tY.value, [10, 100], [40, 200], Extrapolate.CLAMP);
  const gestureEvent = useAnimatedGestureHandler({
    onStart: (event, context) => {
      context.start_tY = tY.value;
    },
    onActive: (event, context) => {
      tY.value = event.translationY;

      console.log('tY.value', tY.value);
      console.log('width', width);
    },
    onEnd: () => {
      tY.value = withSpring(0);
    },
  });

  const sz = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateY: tY.value,
        },
      ],
    };
  });
  return (
    <View>
      <Text>hello</Text>
      <Animated.View style={{...s.pan2, width}} />
      <PanGestureHandler onGestureEvent={gestureEvent}>
        <Animated.View style={[s.pan, sz]} />
      </PanGestureHandler>
    </View>
  );
};

const s = StyleSheet.create({
  pan: {
    width: 80,
    height: 80,
    backgroundColor: 'teal',
  },
  pan2: {
    height: 80,
    backgroundColor: 'gray',
  },
});

export default App;

The interpolate function in Reanimated2 is a pure function. It takes arguments and returns a value.

You have two options here:

  1. Use and log interpolate inside the worklet (useAnimatedStyle or inside any of the gesture handlers)
  2. Wrap that interpolate call with useDerivedValue - it returns a shared value, so make sure to use .value:
const width = useDerivedValue(() => {
  return interpolate(...);
});

Works perfectly now
thanks alot @terrysahaidak, :)

I used the derivedValue also had to use useAnimatedStyle to make it work.

just wonder why first syntax does not work and we need to use the second one
image

useAnimatedStyle body is being executed on the UI Thread. When you pass its result (styles) to Animated.View as style, it bounds that style to that view and tells "if something changes in the AnimatesStyles, please update the view".

Since you can return different styles at any time from useAnimatedStyle, you cannot just "spread" it.

Also, you can no longer pass animated values (now they are shared values) as style properties directly.

@terrysahaidak Great explanation.
What about clamping only left or only right? do they go as 5th and 6th parameters??

Seems like these are missing right now. Could you open a new issue for this?

@terrysahaidak indeed I will open a new one, what about color interpolations, is it possible in v2?

It is. Check out the first example in the example app.

@terrysahaidak I noticed it is basically using a value for HSL color, I wonder if it is possible like the "interpolateColors" from reanimated v1;

https://docs.swmansion.com/react-native-reanimated/docs/1.x.x/nodes/interpolateColors

What is your use case? Do you want to be able to interpolate separately r/g/b?

@terrysahaidak
Asking to see if I am able to do like the following

interpolateColors( //or interpolate()
   someValue.value, 
   [1, 100],
   [ 'red' , 'gold' ] //or HEX values
   Extrapolate.CLAMP
)

I believe @Szymon20000 has wrote some color interpolation logic already.

@terrysahaidak Will we have it on next updated?

@wcandillon has more context on this

Was this page helpful?
0 / 5 - 0 ratings