0

I try to animate a view to hide and show it. the duration is ok to open it (500), but it doesn't work when I close it, the duration is not respected (it closes directly).

Here is my code:

const {height, width} = Dimensions.get('window');

  const [initialHeight] = useState(new Animated.Value(0));

  useEffect(() => {
    if (state === true) {
      Animated.timing(initialHeight, {
        toValue: height - 400,
        duration: 500,
      }).start();
    } else {
      Animated.timing(initialHeight, {
        toValue: 0,
        duration: 500,
      }).start();
    }
  }, [height, initialHeight, state]);

...

<Animated.View style={{height: initialHeight, paddingVertical: 12}}>

What am I missing?

---Edit

I made this change, but it didn't solve the problem:

const [initialHeight, setInitialHeight] = useState(new Animated.Value(0));

  useEffect(() => {
    if (state === true) {
      Animated.timing(initialHeight, {
        toValue: height - 400,
        duration: 500,
      }).start(() => {
        setInitialHeight(new Animated.Value(height - 400));
      });
    } else {
      Animated.timing(initialHeight, {
        toValue: 0,
        duration: 500,
      }).start(() => {
        setInitialHeight(new Animated.Value(0));
      });
    }
  }, [height, initialHeight, state]);
Sylvain
  • 509
  • 1
  • 7
  • 17
  • 1
    What is the `state` variable? – Clarity Nov 25 '19 at 21:10
  • it's a boolean. It's a prop passed from the containing component. When it's true, the animation works, when it's false, it's like the view is not animated, it's hidden directly. – Sylvain Nov 25 '19 at 21:29

2 Answers2

0

You can use useRef to store your Animated Value:

const initialHeight = useRef(new Animated.Value(0)).current;

And you don't have to update it with manually:

useEffect(() => {
    if (state) { //If state is a boolean, you don't need to do === true
      Animated.timing(initialHeight, {
        toValue: height - 400,
        duration: 500,
      }).start();
    } else {
      Animated.timing(initialHeight, {
        toValue: 0,
        duration: 500,
      }).start();
    }
  }, [state]); // If you want to initiate your animation only on this prop change

Don't forget to check the result of height - 400. Each animation, it will take 500ms to go from height - 400 to 0 and reverse.

Fromwood
  • 506
  • 3
  • 6
0

Well, I finally found the problem, and with it the solution. The component was re-rendering completely everytime the prop state changed. So I changed the state variable in the parent component to a object like this: {firstRender: true, opened: false} and changed the values of the initial height according to those parameters. It works like a charm! I certain that there is a better solution, but after searching for hours I couldn't find any.

Sylvain
  • 509
  • 1
  • 7
  • 17