Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS Transitions - Why doesn't this work?

I'd like to transition one element as it changes to another element.

I've got 3 examples:

  • one that works, but uses a list of items that are kept around (jsfiddle)
  • one that doesnt work, and only keeps one item around, depending on the state (jsfiddle)
  • another one that doesn't work, that keeps both items around and hides/shows them (jsfiddle using hide/show)

What I want is more like the second one, which is a very slight variation of the first attempt that works.

Option 1:

/** @jsx React.DOM */

var ReactTransitionGroup = React.addons.TransitionGroup;

var TodoList = React.createClass({
  getInitialState: function() {
    return {items: ['hello', 'world', 'click', 'me']};
  },
  handleAdd: function() {
    var newItems =
      this.state.items.concat([prompt('Enter some text')]);
    this.setState({items: newItems});
  },
  handleRemove: function(i) {
    var newItems = this.state.items;
    newItems.splice(i, 1)
    this.setState({items: newItems});
    },

    render: function() {
        var items = this.state.items.map(function(item, i) {
            return (
                <div key={item} onClick={this.handleRemove.bind(this, i)}>
                    {item}
                </div>
            );
        }.bind(this));

        return (
            <div>
                <div><button onClick={this.handleAdd} /></div>
                <ReactTransitionGroup transitionName="example">
                    {items}
                </ReactTransitionGroup>
            </div>
        );
    }
});

var app = React.renderComponent(<TodoList />, document.body);

Option 2: JSX that doesn't work, but is closer to what I'd like to do (really, hide one view, and show another)

/** @jsx React.DOM */

var ReactTransitionGroup = React.addons.TransitionGroup;

var Test = React.createClass({
  getInitialState: function() {
    return {showOne:true}
  },
  onClick: function() {
    this.setState({showOne:! this.state.showOne});
  },
    render: function() {
      var result;
      if (this.state.showOne)
      {
        result = <div ref="a">One</div>
      }
      else 
      {
        result = <div ref="a">Two</div>
      }

        return (
            <div>
                <div><button onClick={this.onClick}>switch state</button></div>
                <ReactTransitionGroup transitionName="example">
                    {result}
                </ReactTransitionGroup>
            </div>
        );
    }
});

var app = React.renderComponent(<Test />, document.body);

Option 3: Uses hide/show to keep the 2 views around, but still doesn't work.

/** @jsx React.DOM */

var ReactTransitionGroup = React.addons.TransitionGroup;

var Test = React.createClass({
  getInitialState: function() {
    return {showOne:true}
  },
  onClick: function() {
    this.setState({showOne:! this.state.showOne});
  },
    render: function() {
      var result;
      var c1 = this.state.showOne ? "hide" : "show";
      var c2 = this.state.showOne ? "show" : "hide";


      return (
            <div>
                <div><button onClick={this.onClick}>switch state</button></div>
                <ReactTransitionGroup transitionName="example">
        <div className={c1}>One</div>
        <div className={c2}>Two</div>
                </ReactTransitionGroup>
            </div>
        );
    }
});

var app = React.renderComponent(<Test />, document.body);

So long story short - How can I make a transition execute on switching from one main "component" to another? I don't get why option 1 works, but option 2 doesn't!

like image 627
Brad Parks Avatar asked Dec 05 '22 06:12

Brad Parks


1 Answers

React is just changing the content of the DOM because that's all that changed. Give the elements unique keys to make them animate.

  if (this.state.showOne)
  {
    result = <div key="one">One</div>
  }
  else 
  {
    result = <div key="two">Two</div>
  }

JSFiddle

like image 103
Michelle Tilley Avatar answered Dec 08 '22 00:12

Michelle Tilley