Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to start animation when props change (via redux) in React Native?

I have an overlayed view in my React Native app which I need to animate on and off screen when the user pushes a button. I know how to position the view and animate it but I can't work out how to trigger the animation.

My redux store has a very simple state with an isOpen flag saying whether the panel is open or closed. I map the state to the panel component's props and when the isOpen prop changes I want to trigger the open or close animation. Obviously if the user presses the toggle button mid animation the currently running animation needs to be cancelled.

This should be simple but I can't find any examples. Any help would be much appreciated.

like image 881
jonhobbs Avatar asked Aug 25 '18 22:08

jonhobbs


People also ask

Does Redux state change cause re render?

React-redux component does not rerender on store state change.

How do I add React animation to state change?

You can use CSS classes to animate in React import React, { useState } from 'react'; import classNames from 'classnames'; import styles from './App. module. css'; const App = () => { const [animate, setAnimate] = useState(false); const handleClick = () => setAnimate(!

What happens when props change React?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.


1 Answers

React Native

To begin an animation on a change of props you can simply start your animation in componentDidUpdate. Here's an example:

componentDidUpdate(prevProps) {
    if (this.props.isOpen !== prevProps.isOpen) {
        this.state.animation.start();
    }
}

Assuming your animation is defined in the component's state.

React (Browser):

[Not relevant to this question but potentially useful.]

A simple way to do this is using CSS transitions. What you can do is give the panel component a CSS class for closed (or open but I find using the closed/collapsed as a style easier because then the default is open).

Then in your panel's render:

render() {
    const { isOpen } = this.props;

    return <div className={ 'panel' + (isOpen ? '' : ' closed') }></div>
}

And in your CSS:

.panel {
    /* some other styles */
    transition: .5s ease-in;
}

.closed {
    height: 0;
}

This way CSS can handle the animation logic and your concern of clicking the open/close button before the current animation has finished is addressed.

Here are the CSS transition docs: https://developer.mozilla.org/en-US/docs/Web/CSS/transition

Edit: A disadvantage of this method is that height must be explicitly set when the panel is open.

Here's a little example snippet:

function togglePanel() {
  const panel = document.querySelector('div.panel');
  if (panel.classList.contains('closed')) {
    panel.classList.remove('closed');
  } else {
    panel.classList.add('closed');
  }
}
.panel {
  background-color: #00c0de;
  height: 4rem;
  overflow: hidden;
  transition: .5s ease-in;
}

.closed {
  height: 0;
}
<button onclick='togglePanel()'>Toggle Panel</button>

<div class='panel closed'>
  <span>Hello, I'm the panel</span>
</div>
like image 183
Henry Woody Avatar answered Nov 15 '22 07:11

Henry Woody