2

I'm new in React. I have made a small app with a button and a list of image urls. When button is clicked, an image url is added to the list. I render the list of image urls with standard .map function.

I would like to make a fast ui animation effect when the image is displayed: a combination of fade-in and slide-in from left. I tried Velocity.js and found the velocity-react wrapper. But I can not understand how to use it. The same goes for the 'standard' velocity-animate library.

What is best? velocity-react, velocity-animate or something else? And how do I do it?

JSX

<div className="row">
  {
    this.state.images.map( (image, index) => { return this.renderThumb(image, index); } )
  }
</div>

renderThumb function

renderThumb(image, index) {
  return (
    <div ref="tweetImage" key={`image-${index}`} className="col-xs-3 tweetImage">
      <img className="img-thumbnail" src={image} alt="my pic"/>
    </div>
  );
}

velocity-react

I tried to wrap <img> animation opacity from 0 to 1 like this (copied from docs):

<VelocityComponent animation={{ opacity: 1 }} duration={ 500 }>
  <img className="img-thumbnail" src={image} alt="my pic"/>
</VelocityComponent

I keep getting this error:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object


No luck with ReactCSSTransitionGroup either (like suggestions below). Images are shown but without animation:

renderThumb(image, index) {
  return (
    <div ref="tweetImage" key={`image-${index}`} className="col-xs-3">
      <ReactCSSTransitionGroup
        transitionName="example">
          <img className="img-thumbnail" src={image} alt="Ole Frank Jensen"/>
      </ReactCSSTransitionGroup>
    </div>
  );
}

SOLVED:

I moved <ReactCSSTransitionGroup transitionName="example"> outside of the fading component and voilá :-)

render()

<div className="row">
  <ReactCSSTransitionGroup transitionName="example">
    {
      this.state.images.map( (image, index) => { return this.renderThumb(image, index); } )
    }
  </ReactCSSTransitionGroup>
</div>

renderThumb()

renderThumb(image, index) {
  return (
    <div key={`image-${index}`} className="col-xs-3">
      <img className="img-thumbnail" src={image} alt="Ole Frank Jensen"/>
    </div>
  );
}
olefrank
  • 6,452
  • 14
  • 65
  • 90
  • note that you can write `this.state.images.map( (image, index) => { return this.renderThumb(image, index); } )` as `this.state.images.map( this.renderThumb )` – Frido Emans Nov 21 '17 at 00:49

2 Answers2

1

You can use the CSSTransitionGroup provided by react.

https://facebook.github.io/react/docs/animation.html

a simple todo exammple from the docs

class TodoList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {items: ['hello', 'world', 'click', 'me']};
    this.handleAdd = this.handleAdd.bind(this);
  }

  handleAdd() {
    const newItems = this.state.items.concat([
      prompt('Enter some text')
    ]);
    this.setState({items: newItems});
  }

  handleRemove(i) {
    let newItems = this.state.items.slice();
    newItems.splice(i, 1);
    this.setState({items: newItems});
  }

  render() {
    const items = this.state.items.map((item, i) => (
      <div key={item} onClick={() => this.handleRemove(i)}>
        {item}
      </div>
    ));

    return (
      <div>
        <button onClick={this.handleAdd}>Add Item</button>
        <ReactCSSTransitionGroup
          transitionName="example"
          transitionEnterTimeout={500}
          transitionLeaveTimeout={300}>
          {items}
        </ReactCSSTransitionGroup>
      </div>
    );
  }
}
Rei Dien
  • 554
  • 2
  • 12
0

i'd recommend going with React CSS Transistion Group module. It provides an high level animation wrapper for simple animations.


EDIT:

The link will permanently redirect to Animation Add-Ons

ReactTransitionGroup and ReactCSSTransitionGroup have been moved to the react-transition-group package that is maintained by the community.


From the docs

 .example-enter {
  opacity: 0.01;
}

.example-enter.example-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}

.example-leave {
  opacity: 1;
}

.example-leave.example-leave-active {
  opacity: 0.01;
  transition: opacity 300ms ease-in;
}

Where example will be the transistionName for the component that you wish to paint. and -enter,enter-active,-leave,-leave-active stand for the corresponding ticks of the animation cycle. These will be added by React internally as class names to the items.

You can use them to achieve the desired effect in question. A small demo here.

P.S: not sure if this outperforms Velocity.js, havent used that.

Rene
  • 976
  • 1
  • 13
  • 25
semuzaboi
  • 4,972
  • 5
  • 20
  • 35
  • Sorry, I tried your code and adding 'example' as class name to image and wrapping image in but it does not work... – olefrank Mar 21 '17 at 10:38
  • Sorry, that was a mistake from my part.. That should have been `transistionName`. Updated the fiddle as well, to fit your requirement ,used lorem pixel for images. Let me know if t works.:) – semuzaboi Mar 21 '17 at 11:02